When a client of any protocol handler sends a command to initiate SSL/TLS on a connec...
[citadel] / citadel / modules / crypto / serv_crypto.c
1 // Copyright (c) 1987-2021 by the citadel.org team
2 //
3 // This program is open source software; you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License version 3.
5 //
6 // This program is distributed in the hope that it will be useful,
7 // but WITHOUT ANY WARRANTY; without even the implied warranty of
8 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9 // GNU General Public License for more details.
10
11 #include <string.h>
12 #include <unistd.h>
13 #include <sys/stat.h>
14 #include <sys/types.h>
15 #include "sysdep.h"
16
17 #ifdef HAVE_OPENSSL
18 #include <openssl/ssl.h>
19 #include <openssl/err.h>
20 #include <openssl/rand.h>
21 #endif
22
23 #include <time.h>
24
25 #ifdef HAVE_PTHREAD_H
26 #include <pthread.h>
27 #endif
28
29 #ifdef HAVE_SYS_SELECT_H
30 #include <sys/select.h>
31 #endif
32
33 #include <stdio.h>
34 #include <libcitadel.h>
35 #include "server.h"
36 #include "serv_crypto.h"
37 #include "sysdep_decls.h"
38 #include "citadel.h"
39 #include "config.h"
40
41
42 #include "ctdl_module.h"
43
44 #ifdef HAVE_OPENSSL
45 SSL_CTX *ssl_ctx;               /* SSL context */
46 pthread_mutex_t **SSLCritters;  /* Things needing locking */
47
48
49 static unsigned long id_callback(void) {
50         return (unsigned long) pthread_self();
51 }
52
53
54 void destruct_ssl(void) {
55         int a;
56         for (a = 0; a < CRYPTO_num_locks(); a++) 
57                 free(SSLCritters[a]);
58         free (SSLCritters);
59 }
60
61
62 void generate_key(char *keyfilename) {
63         int ret = 0;
64         RSA *rsa = NULL;
65         BIGNUM *bne = NULL;
66         int bits = 2048;
67         unsigned long e = RSA_F4;
68         FILE *fp;
69
70         if (access(keyfilename, R_OK) == 0) {
71                 return;
72         }
73
74         syslog(LOG_INFO, "crypto: generating RSA key pair");
75  
76         // generate rsa key
77         bne = BN_new();
78         ret = BN_set_word(bne,e);
79         if (ret != 1) {
80                 goto free_all;
81         }
82  
83         rsa = RSA_new();
84         ret = RSA_generate_key_ex(rsa, bits, bne, NULL);
85         if (ret != 1) {
86                 goto free_all;
87         }
88
89         // write the key file
90         fp = fopen(keyfilename, "w");
91         if (fp != NULL) {
92                 chmod(keyfilename, 0600);
93                 if (PEM_write_RSAPrivateKey(fp, /* the file */
94                                         rsa,    /* the key */
95                                         NULL,   /* no enc */
96                                         NULL,   /* no passphr */
97                                         0,      /* no passphr */
98                                         NULL,   /* no callbk */
99                                         NULL    /* no callbk */
100                 ) != 1) {
101                         syslog(LOG_ERR, "crypto: cannot write key: %s", ERR_reason_error_string(ERR_get_error()));
102                         unlink(keyfilename);
103                 }
104                 fclose(fp);
105         }
106
107     // 4. free
108 free_all:
109     RSA_free(rsa);
110     BN_free(bne);
111 }
112
113
114 void init_ssl(void) {
115         const SSL_METHOD *ssl_method;
116         RSA *rsa = NULL;
117         X509_REQ *req = NULL;
118         X509 *cer = NULL;
119         EVP_PKEY *pk = NULL;
120         EVP_PKEY *req_pkey = NULL;
121         X509_NAME *name = NULL;
122         FILE *fp;
123
124         SSLCritters = malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t *));
125         if (!SSLCritters) {
126                 syslog(LOG_ERR, "crypto: can't allocate memory!");
127                 exit(CTDLEXIT_CRYPTO);
128         }
129         else {
130                 int a;
131
132                 for (a = 0; a < CRYPTO_num_locks(); a++) {
133                         SSLCritters[a] = malloc(sizeof(pthread_mutex_t));
134                         if (!SSLCritters[a]) {
135                                 syslog(LOG_ERR, "crypto: can't allocate memory!!");
136                                 exit(CTDLEXIT_CRYPTO);
137                         }
138                         pthread_mutex_init(SSLCritters[a], NULL);
139                 }
140         }
141
142         /*
143          * Initialize SSL transport layer
144          */
145         SSL_library_init();
146         SSL_load_error_strings();
147         ssl_method = SSLv23_server_method();
148         if (!(ssl_ctx = SSL_CTX_new(ssl_method))) {
149                 syslog(LOG_ERR, "crypto: SSL_CTX_new failed: %s", ERR_reason_error_string(ERR_get_error()));
150                 return;
151         }
152         if (!(SSL_CTX_set_cipher_list(ssl_ctx, CIT_CIPHERS))) {
153                 syslog(LOG_ERR, "crypto: No ciphers available");
154                 SSL_CTX_free(ssl_ctx);
155                 ssl_ctx = NULL;
156                 return;
157         }
158
159         CRYPTO_set_locking_callback(ssl_lock);
160         CRYPTO_set_id_callback(id_callback);
161
162         mkdir(ctdl_key_dir, 0700);              // If the keys directory does not exist, create it
163         generate_key(file_crpt_file_key);       // If a private key does not exist, create it
164
165         /*
166          * If there is no certificate file on disk, we will be generating a self-signed certificate
167          * in the next step.  Therefore, if we have neither a CSR nor a certificate, generate
168          * the CSR in this step so that the next step may commence.
169          */
170         if ( (access(file_crpt_file_cer, R_OK) != 0) && (access(file_crpt_file_csr, R_OK) != 0) ) {
171                 syslog(LOG_INFO, "crypto: generating a generic certificate signing request.");
172
173                 /*
174                  * Read our key from the file.  No, we don't just keep this
175                  * in memory from the above key-generation function, because
176                  * there is the possibility that the key was already on disk
177                  * and we didn't just generate it now.
178                  */
179                 fp = fopen(file_crpt_file_key, "r");
180                 if (fp) {
181                         rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
182                         fclose(fp);
183                 }
184
185                 if (rsa) {
186
187                         /* Create a public key from the private key */
188                         if (pk=EVP_PKEY_new(), pk != NULL) {
189                                 EVP_PKEY_assign_RSA(pk, rsa);
190                                 if (req = X509_REQ_new(), req != NULL) {
191
192                                         /* Set the public key */
193                                         X509_REQ_set_pubkey(req, pk);
194                                         X509_REQ_set_version(req, 0L);
195
196                                         name = X509_REQ_get_subject_name(req);
197
198                                         /* Tell it who we are */
199                                         X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (unsigned const char *)"ZZ", -1, -1, 0);
200                                         X509_NAME_add_entry_by_txt(name, "ST", MBSTRING_ASC, (unsigned const char *)"The World", -1, -1, 0);
201                                         X509_NAME_add_entry_by_txt(name, "L", MBSTRING_ASC, (unsigned const char *)"My Location", -1, -1, 0);
202                                         X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, (unsigned const char *)"Generic certificate", -1, -1, 0);
203                                         X509_NAME_add_entry_by_txt(name, "OU", MBSTRING_ASC, (unsigned const char *)"Citadel server", -1, -1, 0);
204                                         X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (unsigned const char *)"*", -1, -1, 0);
205                                         X509_REQ_set_subject_name(req, name);
206
207                                         /* Sign the CSR */
208                                         if (!X509_REQ_sign(req, pk, EVP_md5())) {
209                                                 syslog(LOG_ERR, "crypto: X509_REQ_sign(): error");
210                                         }
211                                         else {
212                                                 /* Write it to disk. */ 
213                                                 fp = fopen(file_crpt_file_csr, "w");
214                                                 if (fp != NULL) {
215                                                         chmod(file_crpt_file_csr, 0600);
216                                                         PEM_write_X509_REQ(fp, req);
217                                                         fclose(fp);
218                                                 }
219                                         }
220
221                                         X509_REQ_free(req);
222                                 }
223                         }
224
225                         RSA_free(rsa);
226                 }
227
228                 else {
229                         syslog(LOG_ERR, "crypto: unable to read private key.");
230                 }
231         }
232
233
234         /*
235          * Generate a self-signed certificate if we don't have one.
236          */
237         if (access(file_crpt_file_cer, R_OK) != 0) {
238                 syslog(LOG_INFO, "crypto: generating a generic self-signed certificate.");
239
240                 /* Same deal as before: always read the key from disk because
241                  * it may or may not have just been generated.
242                  */
243                 fp = fopen(file_crpt_file_key, "r");
244                 if (fp) {
245                         rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
246                         fclose(fp);
247                 }
248
249                 /* This also holds true for the CSR. */
250                 req = NULL;
251                 cer = NULL;
252                 pk = NULL;
253                 if (rsa) {
254                         if (pk=EVP_PKEY_new(), pk != NULL) {
255                                 EVP_PKEY_assign_RSA(pk, rsa);
256                         }
257
258                         fp = fopen(file_crpt_file_csr, "r");
259                         if (fp) {
260                                 req = PEM_read_X509_REQ(fp, NULL, NULL, NULL);
261                                 fclose(fp);
262                         }
263
264                         if (req) {
265                                 if (cer = X509_new(), cer != NULL) {
266                                         ASN1_INTEGER_set(X509_get_serialNumber(cer), 0);
267                                         X509_set_issuer_name(cer, X509_REQ_get_subject_name(req));
268                                         X509_set_subject_name(cer, X509_REQ_get_subject_name(req));
269                                         X509_gmtime_adj(X509_get_notBefore(cer),0);
270                                         X509_gmtime_adj(X509_get_notAfter(cer),(long)60*60*24*SIGN_DAYS);
271                                         req_pkey = X509_REQ_get_pubkey(req);
272                                         X509_set_pubkey(cer, req_pkey);
273                                         EVP_PKEY_free(req_pkey);
274                                         
275                                         /* Sign the cert */
276                                         if (!X509_sign(cer, pk, EVP_md5())) {
277                                                 syslog(LOG_ERR, "crypto: X509_sign() error");
278                                         }
279                                         else {
280                                                 /* Write it to disk. */ 
281                                                 fp = fopen(file_crpt_file_cer, "w");
282                                                 if (fp != NULL) {
283                                                         chmod(file_crpt_file_cer, 0600);
284                                                         PEM_write_X509(fp, cer);
285                                                         fclose(fp);
286                                                 }
287                                         }
288                                         X509_free(cer);
289                                 }
290                         }
291
292                         RSA_free(rsa);
293                 }
294         }
295
296
297         /*
298          * Now try to bind to the key and certificate.
299          */
300         SSL_CTX_use_certificate_chain_file(ssl_ctx, file_crpt_file_cer);
301         SSL_CTX_use_PrivateKey_file(ssl_ctx, file_crpt_file_key, SSL_FILETYPE_PEM);
302         if ( !SSL_CTX_check_private_key(ssl_ctx) ) {
303                 syslog(LOG_ERR, "crypto: cannot install certificate: %s", ERR_reason_error_string(ERR_get_error()));
304         }
305
306         /* Finally let the server know we're here */
307         CtdlRegisterProtoHook(cmd_stls, "STLS", "Start SSL/TLS session");
308         CtdlRegisterProtoHook(cmd_gtls, "GTLS", "Get SSL/TLS session status");
309         CtdlRegisterSessionHook(endtls, EVT_STOP, PRIO_STOP + 10);
310 }
311
312
313 // client_write_ssl() Send binary data to the client encrypted.
314 void client_write_ssl(const char *buf, int nbytes) {
315         int retval;
316         int nremain;
317         char junk[1];
318
319         nremain = nbytes;
320
321         while (nremain > 0) {
322                 if (SSL_want_write(CC->ssl)) {
323                         if ((SSL_read(CC->ssl, junk, 0)) < 1) {
324                                 syslog(LOG_DEBUG, "crypto: SSL_read in client_write: %s", ERR_reason_error_string(ERR_get_error()));
325                         }
326                 }
327                 retval =
328                     SSL_write(CC->ssl, &buf[nbytes - nremain], nremain);
329                 if (retval < 1) {
330                         long errval;
331
332                         errval = SSL_get_error(CC->ssl, retval);
333                         if (errval == SSL_ERROR_WANT_READ ||
334                             errval == SSL_ERROR_WANT_WRITE) {
335                                 sleep(1);
336                                 continue;
337                         }
338                         syslog(LOG_DEBUG, "crypto: SSL_write got error %ld, ret %d", errval, retval);
339                         if (retval == -1) {
340                                 syslog(LOG_DEBUG, "crypto: errno is %d", errno);
341                         }
342                         endtls();
343                         client_write(&buf[nbytes - nremain], nremain);
344                         return;
345                 }
346                 nremain -= retval;
347         }
348 }
349
350
351 // read data from the encrypted layer.
352 int client_read_sslbuffer(StrBuf *buf, int timeout) {
353         char sbuf[16384]; /* OpenSSL communicates in 16k blocks, so let's speak its native tongue. */
354         int rlen;
355         char junk[1];
356         SSL *pssl = CC->ssl;
357
358         if (pssl == NULL) return(-1);
359
360         while (1) {
361                 if (SSL_want_read(pssl)) {
362                         if ((SSL_write(pssl, junk, 0)) < 1) {
363                                 syslog(LOG_DEBUG, "crypto: SSL_write in client_read");
364                         }
365                 }
366                 rlen = SSL_read(pssl, sbuf, sizeof(sbuf));
367                 if (rlen < 1) {
368                         long errval;
369
370                         errval = SSL_get_error(pssl, rlen);
371                         if (errval == SSL_ERROR_WANT_READ || errval == SSL_ERROR_WANT_WRITE) {
372                                 sleep(1);
373                                 continue;
374                         }
375                         syslog(LOG_DEBUG, "crypto: SSL_read got error %ld", errval);
376                         endtls();
377                         return (-1);
378                 }
379                 StrBufAppendBufPlain(buf, sbuf, rlen, 0);
380                 return rlen;
381         }
382         return (0);
383 }
384
385
386 int client_readline_sslbuffer(StrBuf *Line, StrBuf *IOBuf, const char **Pos, int timeout) {
387         const char *pos = NULL;
388         const char *pLF;
389         int len, rlen;
390         int nSuccessLess = 0;
391         const char *pch = NULL;
392         
393         if ((Line == NULL) || (Pos == NULL) || (IOBuf == NULL))
394         {
395                 if (Pos != NULL)
396                 {
397                         *Pos = NULL;
398                 }
399                 return -1;
400         }
401
402         pos = *Pos;
403         if ((StrLength(IOBuf) > 0) && (pos != NULL) && (pos < ChrPtr(IOBuf) + StrLength(IOBuf))) 
404         {
405                 pch = pos;
406                 pch = strchr(pch, '\n');
407                 
408                 if (pch == NULL) {
409                         StrBufAppendBufPlain(Line, pos, StrLength(IOBuf) - (pos - ChrPtr(IOBuf)), 0);
410                         FlushStrBuf(IOBuf);
411                         *Pos = NULL;
412                 }
413                 else {
414                         int n = 0;
415                         if ((pch > ChrPtr(IOBuf)) && 
416                             (*(pch - 1) == '\r')) {
417                                 n = 1;
418                         }
419                         StrBufAppendBufPlain(Line, pos, 
420                                              (pch - pos - n), 0);
421
422                         if (StrLength(IOBuf) <= (pch - ChrPtr(IOBuf) + 1)) {
423                                 FlushStrBuf(IOBuf);
424                                 *Pos = NULL;
425                         }
426                         else 
427                                 *Pos = pch + 1;
428                         return StrLength(Line);
429                 }
430         }
431
432         pLF = NULL;
433         while ((nSuccessLess < timeout) && 
434                (pLF == NULL) &&
435                (CC->ssl != NULL)) {
436
437                 rlen = client_read_sslbuffer(IOBuf, timeout);
438                 if (rlen < 1) {
439                         return -1;
440                 }
441                 else if (rlen > 0) {
442                         pLF = strchr(ChrPtr(IOBuf), '\n');
443                 }
444         }
445         *Pos = NULL;
446         if (pLF != NULL) {
447                 pos = ChrPtr(IOBuf);
448                 len = pLF - pos;
449                 if (len > 0 && (*(pLF - 1) == '\r') )
450                         len --;
451                 StrBufAppendBufPlain(Line, pos, len, 0);
452                 if (pLF + 1 >= ChrPtr(IOBuf) + StrLength(IOBuf))
453                 {
454                         FlushStrBuf(IOBuf);
455                 }
456                 else 
457                         *Pos = pLF + 1;
458                 return StrLength(Line);
459         }
460         return -1;
461 }
462
463
464 int client_read_sslblob(StrBuf *Target, long bytes, int timeout) {
465         long baselen;
466         long RemainRead;
467         int retval = 0;
468
469         baselen = StrLength(Target);
470
471         if (StrLength(CC->RecvBuf.Buf) > 0)
472         {
473                 long RemainLen;
474                 long TotalLen;
475                 const char *pchs;
476
477                 if (CC->RecvBuf.ReadWritePointer == NULL)
478                 {
479                         CC->RecvBuf.ReadWritePointer = ChrPtr(CC->RecvBuf.Buf);
480                 }
481                 pchs = ChrPtr(CC->RecvBuf.Buf);
482                 TotalLen = StrLength(CC->RecvBuf.Buf);
483                 RemainLen = TotalLen - (pchs - CC->RecvBuf.ReadWritePointer);
484                 if (RemainLen > bytes)
485                 {
486                         RemainLen = bytes;
487                 }
488                 if (RemainLen > 0)
489                 {
490                         StrBufAppendBufPlain(Target, CC->RecvBuf.ReadWritePointer, RemainLen, 0);
491                         CC->RecvBuf.ReadWritePointer += RemainLen;
492                 }
493                 if ((ChrPtr(CC->RecvBuf.Buf) + StrLength(CC->RecvBuf.Buf)) <= CC->RecvBuf.ReadWritePointer)
494                 {
495                         CC->RecvBuf.ReadWritePointer = NULL;
496                         FlushStrBuf(CC->RecvBuf.Buf);
497                 }
498         }
499
500         if (StrLength(Target) >= bytes + baselen) {
501                 return 1;
502         }
503
504         CC->RecvBuf.ReadWritePointer = NULL;
505
506         while ((StrLength(Target) < bytes + baselen) && (retval >= 0)) {
507                 retval = client_read_sslbuffer(CC->RecvBuf.Buf, timeout);
508                 if (retval >= 0) {
509                         RemainRead = bytes - (StrLength (Target) - baselen);
510                         if (RemainRead < StrLength(CC->RecvBuf.Buf))
511                         {
512                                 StrBufAppendBufPlain(
513                                         Target, 
514                                         ChrPtr(CC->RecvBuf.Buf), 
515                                         RemainRead, 0);
516                                 CC->RecvBuf.ReadWritePointer = ChrPtr(CC->RecvBuf.Buf) + RemainRead;
517                                 break;
518                         }
519                         StrBufAppendBuf(Target, CC->RecvBuf.Buf, 0); /* todo: Buf > bytes? */
520                         FlushStrBuf(CC->RecvBuf.Buf);
521                 }
522                 else {
523                         FlushStrBuf(CC->RecvBuf.Buf);
524                         return -1;
525         
526                 }
527         }
528         return 1;
529 }
530
531
532 // CtdlStartTLS() starts SSL/TLS encryption for the current session.  It
533 // must be supplied with pre-generated strings for responses of "ok," "no
534 // support for TLS," and "error" so that we can use this in any protocol.
535 void CtdlStartTLS(char *ok_response, char *nosup_response, char *error_response) {
536         int retval, bits, alg_bits;
537
538         if (CC->redirect_ssl) {
539                 syslog(LOG_ERR, "crypto: attempt to begin SSL on an already encrypted connection");
540                 if (error_response != NULL) {
541                         cprintf("%s", error_response);
542                 }
543                 return;
544         }
545
546         if (!ssl_ctx) {
547                 syslog(LOG_ERR, "crypto: SSL failed: no ssl_ctx exists?");
548                 if (nosup_response != NULL) cprintf("%s", nosup_response);
549                 return;
550         }
551         if (!(CC->ssl = SSL_new(ssl_ctx))) {
552                 syslog(LOG_ERR, "crypto: SSL_new failed: %s", ERR_reason_error_string(ERR_get_error()));
553                 if (error_response != NULL) {
554                         cprintf("%s", error_response);
555                 }
556                 return;
557         }
558         if (!(SSL_set_fd(CC->ssl, CC->client_socket))) {
559                 syslog(LOG_ERR, "crypto: SSL_set_fd failed: %s", ERR_reason_error_string(ERR_get_error()));
560                 SSL_free(CC->ssl);
561                 CC->ssl = NULL;
562                 if (error_response != NULL) cprintf("%s", error_response);
563                 return;
564         }
565         if (ok_response != NULL) cprintf("%s", ok_response);
566         retval = SSL_accept(CC->ssl);
567         if (retval < 1) {
568                 /*
569                  * Can't notify the client of an error here; they will
570                  * discover the problem at the SSL layer and should
571                  * revert to unencrypted communications.
572                  */
573                 long errval;
574                 char error_string[128];
575
576                 errval = SSL_get_error(CC->ssl, retval);
577                 syslog(LOG_ERR, "crypto: SSL_accept failed: retval=%d, errval=%ld, err=%s",
578                         retval,
579                         errval,
580                         ERR_error_string(errval, error_string)
581                 );
582                 SSL_free(CC->ssl);
583                 CC->ssl = NULL;
584                 return;
585         }
586         // BIO_set_close(CC->ssl->rbio, BIO_NOCLOSE); not needed anymore in openssl 1.1 ?
587         bits = SSL_CIPHER_get_bits(SSL_get_current_cipher(CC->ssl), &alg_bits);
588         syslog(LOG_INFO, "crypto: SSL/TLS using %s on %s (%d of %d bits)",
589                 SSL_CIPHER_get_name(SSL_get_current_cipher(CC->ssl)),
590                 SSL_CIPHER_get_version(SSL_get_current_cipher(CC->ssl)),
591                 bits, alg_bits
592         );
593         CC->redirect_ssl = 1;
594 }
595
596
597 // cmd_stls() starts SSL/TLS encryption for the current session
598 void cmd_stls(char *params) {
599         char ok_response[SIZ];
600         char nosup_response[SIZ];
601         char error_response[SIZ];
602
603         unbuffer_output();
604
605         sprintf(ok_response, "%d Begin TLS negotiation now\n", CIT_OK);
606         sprintf(nosup_response, "%d TLS not supported here\n", ERROR + CMD_NOT_SUPPORTED);
607         sprintf(error_response, "%d TLS negotiation error\n", ERROR + INTERNAL_ERROR);
608
609         CtdlStartTLS(ok_response, nosup_response, error_response);
610 }
611
612
613 // cmd_gtls() returns status info about the TLS connection
614 void cmd_gtls(char *params) {
615         int bits, alg_bits;
616
617         if (!CC->ssl || !CC->redirect_ssl) {
618                 cprintf("%d Session is not encrypted.\n", ERROR);
619                 return;
620         }
621         bits =
622             SSL_CIPHER_get_bits(SSL_get_current_cipher(CC->ssl),
623                                 &alg_bits);
624         cprintf("%d %s|%s|%d|%d\n", CIT_OK,
625                 SSL_CIPHER_get_version(SSL_get_current_cipher(CC->ssl)),
626                 SSL_CIPHER_get_name(SSL_get_current_cipher(CC->ssl)),
627                 alg_bits, bits);
628 }
629
630
631 // endtls() shuts down the TLS connection
632 //
633 // WARNING:  This may make your session vulnerable to a known plaintext
634 // attack in the current implmentation.
635 void endtls(void) {
636         if (!CC->ssl) {
637                 CC->redirect_ssl = 0;
638                 return;
639         }
640
641         syslog(LOG_INFO, "crypto: ending SSL/TLS");
642         SSL_shutdown(CC->ssl);
643         SSL_free(CC->ssl);
644         CC->ssl = NULL;
645         CC->redirect_ssl = 0;
646 }
647
648
649 // ssl_lock() callback for OpenSSL mutex locks
650 void ssl_lock(int mode, int n, const char *file, int line) {
651         if (mode & CRYPTO_LOCK) {
652                 pthread_mutex_lock(SSLCritters[n]);
653         }
654         else {
655                 pthread_mutex_unlock(SSLCritters[n]);
656         }
657 }
658 #endif                          /* HAVE_OPENSSL */