]> git.sur5r.net Git - openldap/blob - libraries/libldap/tls.c
a12783415205487c39e715023e623d7bec49feae
[openldap] / libraries / libldap / tls.c
1 /*
2  * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
3  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
4  *
5  * tls.c - Handle tls/ssl using SSLeay or OpenSSL.
6  */
7
8 #include "portable.h"
9
10 #ifdef HAVE_TLS
11
12 #include <stdio.h>
13 #include <stdlib.h>
14
15 #include <ac/errno.h>
16 #include <ac/socket.h>
17 #include <ac/string.h>
18 #include <ac/time.h>
19 #include <ac/unistd.h>
20
21 #include "ldap-int.h"
22
23 #ifdef LDAP_R_COMPILE
24 #include <ldap_pvt_thread.h>
25 #endif
26
27 #ifdef HAVE_OPENSSL_SSL_H
28 #include <openssl/ssl.h>
29 #elif defined( HAVE_SSL_H )
30 #include <ssl.h>
31 #endif
32
33 static char *tls_opt_certfile = NULL;
34 static char *tls_opt_keyfile = NULL;
35 static char *tls_opt_cacertfile = NULL;
36 static char *tls_opt_cacertdir = NULL;
37 static int  tls_opt_require_cert = 0;
38
39 #define HAS_TLS( sb ) ((sb)->sb_io==&tls_io)
40
41 static int tls_setup( Sockbuf *sb, void *arg );
42 static int tls_remove( Sockbuf *sb );
43 static ber_slen_t tls_read( Sockbuf *sb, void *buf, ber_len_t len );
44 static ber_slen_t tls_write( Sockbuf *sb, void *buf, ber_len_t len );
45 static int tls_close( Sockbuf *sb );
46 static int tls_report_error( void );
47
48 static Sockbuf_IO tls_io=
49 {
50    tls_setup,
51    tls_remove,
52    tls_read,
53    tls_write,
54    tls_close
55 };
56
57 static int tls_verify_cb( int ok, X509_STORE_CTX *ctx );
58
59 static SSL_CTX *tls_def_ctx = NULL;
60
61 #ifdef LDAP_R_COMPILE
62 /*
63  * provide mutexes for the SSLeay library.
64  */
65 static ldap_pvt_thread_mutex_t  tls_mutexes[CRYPTO_NUM_LOCKS];
66
67 static void tls_locking_cb( int mode, int type, const char *file, int line )
68 {
69         if ( mode & CRYPTO_LOCK ) {
70                 ldap_pvt_thread_mutex_lock( tls_mutexes+type );
71         } else {
72                 ldap_pvt_thread_mutex_unlock( tls_mutexes+type );
73         }
74 }
75
76 /*
77  * an extra mutex for the default ctx.
78  */
79
80 static ldap_pvt_thread_mutex_t tls_def_ctx_mutex;
81
82 static void tls_init_threads( void )
83 {
84         int i;
85
86         for( i=0; i< CRYPTO_NUM_LOCKS ; i++ ) {
87                 ldap_pvt_thread_mutex_init( tls_mutexes+i );
88         }
89         CRYPTO_set_locking_callback( tls_locking_cb );
90         /* FIXME: the thread id should be added somehow... */
91
92         ldap_pvt_thread_mutex_init( &tls_def_ctx_mutex );
93 }
94 #endif /* LDAP_R_COMPILE */
95
96 /*
97  * Initialize tls system. Should be called only once.
98  */
99 int
100 ldap_pvt_tls_init( void )
101 {
102         static int tls_initialized = 0;
103
104         if ( tls_initialized )
105                 return -1;
106 #ifdef LDAP_R_COMPILE
107         tls_init_threads();
108 #endif
109         SSL_load_error_strings();
110         SSLeay_add_ssl_algorithms();
111         return 0;
112 }
113
114 /*
115  * initialize the default context
116  */
117 int
118 ldap_pvt_tls_init_def_ctx( void )
119 {
120 #ifdef LDAP_R_COMPILE
121         ldap_pvt_thread_mutex_lock( &tls_def_ctx_mutex );
122 #endif
123         if ( tls_def_ctx == NULL ) {
124                 tls_def_ctx = SSL_CTX_new( SSLv23_method() );
125                 if ( tls_def_ctx == NULL ) {
126                         Debug( LDAP_DEBUG_ANY,
127                                "TLS: could not allocate default ctx.\n",0,0,0);
128                         goto error_exit;
129                 }
130                 if ( !SSL_CTX_set_cipher_list( tls_def_ctx,
131                         "RC4+RSA:HIGH:MEDIUM:LOW:EXP:+SSLv2:+EXP" ) ) {
132                         Debug( LDAP_DEBUG_ANY,
133                                "TLS: could not set cipher list.\n", 0, 0 );
134                         tls_report_error();
135                         goto error_exit;
136                 }
137                 if ( !SSL_CTX_load_verify_locations( tls_def_ctx,
138                                                      tls_opt_cacertfile,
139                                                      tls_opt_cacertdir ) ||
140                      !SSL_CTX_set_default_verify_paths( tls_def_ctx ) ) {
141                         Debug( LDAP_DEBUG_ANY,
142                 "TLS: could not load verify locations (file:`%s',dir:`%s').\n",
143                                tls_opt_cacertfile,tls_opt_cacertdir,0);
144                         goto error_exit;
145                 }
146                 if ( tls_opt_keyfile &&
147                      !SSL_CTX_use_PrivateKey_file( tls_def_ctx,
148                                                    tls_opt_keyfile,
149                                                    SSL_FILETYPE_PEM ) ) {
150                         Debug( LDAP_DEBUG_ANY,
151                                "TLS: could not use key file `%s'.\n",
152                                tls_opt_keyfile,0,0);
153                         goto error_exit;
154                 }
155                 if ( tls_opt_certfile &&
156                      !SSL_CTX_use_certificate_file( tls_def_ctx,
157                                                     tls_opt_certfile,
158                                                     SSL_FILETYPE_PEM ) ) {
159                         Debug( LDAP_DEBUG_ANY,
160                                "TLS: could not use certificate `%s'.\n",
161                                tls_opt_certfile,0,0);
162                         goto error_exit;
163                 }
164                 SSL_CTX_set_verify( tls_def_ctx, (tls_opt_require_cert) ?
165                         (SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT) :
166                         SSL_VERIFY_PEER, tls_verify_cb );
167         }
168 #ifdef LDAP_R_COMPILE
169         ldap_pvt_thread_mutex_unlock( &tls_def_ctx_mutex );
170 #endif
171         return 0;
172 error_exit:
173 #ifdef LDAP_R_COMPILE
174         ldap_pvt_thread_mutex_unlock( &tls_def_ctx_mutex );
175 #endif
176         return -1;
177 }
178
179 static SSL *
180 alloc_handle( Sockbuf *sb, void *ctx_arg )
181 {
182         int     err;
183         SSL_CTX *ctx;
184         SSL     *ssl;
185
186         if ( ctx_arg ) {
187                 ctx = (SSL_CTX *) ctx_arg;
188         } else {
189                 if ( ldap_pvt_tls_init_def_ctx() < 0 )
190                         return NULL;
191                 ctx=tls_def_ctx;
192         }
193
194         ssl = SSL_new( ctx );
195         if ( ssl == NULL ) {
196                 Debug( LDAP_DEBUG_ANY,"TLS: can't create ssl handle.\n",0,0,0);
197                 return NULL;
198         }
199
200         SSL_set_fd( ssl, ber_pvt_sb_get_desc( sb ) );
201         return ssl;
202 }
203
204 static void
205 update_flags( Sockbuf *sb, SSL * ssl )
206 {
207         sb->sb_trans_needs_read  = SSL_want_read(ssl) ? 1 : 0;
208         sb->sb_trans_needs_write = SSL_want_write(ssl) ? 1 : 0;
209 }
210
211 /*
212  * Call this to do a TLS connect on a sockbuf. ctx_arg can be
213  * a SSL_CTX * or NULL, in which case the default ctx is used.
214  *
215  * Return value:
216  *
217  *  0 - Success. Connection is ready for communication.
218  * <0 - Error. Can't create a TLS stream.
219  * >0 - Partial success.
220  *        Do a select (using information from lber_pvt_sb_needs_{read,write}
221  *              and call again.
222  */
223
224 int
225 ldap_pvt_tls_connect( Sockbuf *sb, void *ctx_arg )
226 {
227         int     err;
228         SSL     *ssl;
229
230         if ( HAS_TLS( sb ) ) {
231                 ssl = (SSL *) sb->sb_iodata;
232         } else {
233                 ssl = alloc_handle( sb, ctx_arg );
234                 if ( ssl == NULL )
235                         return -1;
236                 ber_pvt_sb_clear_io( sb );
237                 ber_pvt_sb_set_io( sb, &tls_io, (void *)ssl );
238         }
239
240         err = SSL_connect( ssl );
241
242         if ( err <= 0 ) {
243                 if (
244 #ifdef EWOULDBLOCK
245                     (errno==EWOULDBLOCK) ||
246 #endif
247 #ifdef EAGAIN
248                     (errno==EAGAIN) ||
249 #endif
250                     (0)) {
251                         update_flags( sb, ssl );
252                         return 1;
253                 }
254                 Debug( LDAP_DEBUG_ANY,"TLS: can't connect.\n",0,0,0);
255                 ber_pvt_sb_clear_io( sb );
256                 ber_pvt_sb_set_io( sb, &ber_pvt_sb_io_tcp, NULL );
257                 return -1;
258         }
259         return 0;
260 }
261
262 /*
263  * Call this to do a TLS accept on a sockbuf.
264  * Everything else is the same as with tls_connect.
265  */
266 int
267 ldap_pvt_tls_accept( Sockbuf *sb, void *ctx_arg )
268 {
269         int     err;
270         SSL     *ssl;
271
272         if ( HAS_TLS( sb ) ) {
273                 ssl = (SSL *) sb->sb_iodata;
274         } else {
275                 ssl = alloc_handle( sb, ctx_arg );
276                 if ( ssl == NULL )
277                         return -1;
278                 ber_pvt_sb_clear_io( sb );
279                 ber_pvt_sb_set_io( sb, &tls_io, (void *)ssl );
280         }
281
282         err = SSL_accept( ssl );
283
284         if ( err <= 0 ) {
285                 if (
286 #ifdef EWOULDBLOCK
287                     (errno==EWOULDBLOCK) ||
288 #endif
289 #ifdef EAGAIN
290                     (errno==EAGAIN) ||
291 #endif
292                     (0)) {
293                         update_flags( sb, ssl );
294                         return 1;
295                 }
296                 Debug( LDAP_DEBUG_ANY,"TLS: can't accept.\n",0,0,0 );
297                 tls_report_error();
298                 ber_pvt_sb_clear_io( sb );
299                 ber_pvt_sb_set_io( sb, &ber_pvt_sb_io_tcp, NULL );
300                 return -1;
301         }
302         return 0;
303 }
304
305 const char *
306 ldap_pvt_tls_get_peer( LDAP *ld )
307 {
308 }
309
310 const char *
311 ldap_pvt_tls_get_peer_issuer( LDAP *ld )
312 {
313 }
314
315 int
316 ldap_pvt_tls_config( struct ldapoptions *lo, int option, const char *arg )
317 {
318         int i;
319
320         switch( option ) {
321         case LDAP_OPT_X_TLS_CACERTFILE:
322         case LDAP_OPT_X_TLS_CACERTDIR:
323         case LDAP_OPT_X_TLS_CERTFILE:
324         case LDAP_OPT_X_TLS_KEYFILE:
325                 return ldap_pvt_tls_set_option( NULL, option, (void *) arg );
326         case LDAP_OPT_X_TLS_REQUIRE_CERT:
327                 i = ( ( strcasecmp( arg, "on" ) == 0 ) ||
328                       ( strcasecmp( arg, "yes" ) == 0) ||
329                       ( strcasecmp( arg, "true" ) == 0 ) );
330                 return ldap_pvt_tls_set_option( NULL, option, (void *) &i );
331         case LDAP_OPT_X_TLS:
332                 if ( strcasecmp( arg, "never" ) == 0 )
333                         return ldap_pvt_tls_set_option( lo, option,
334                                 LDAP_OPT_X_TLS_NEVER );
335                 if ( strcasecmp( arg, "demand" ) == 0 )
336                         return ldap_pvt_tls_set_option( lo, option,
337                                 LDAP_OPT_X_TLS_DEMAND );
338                 if ( strcasecmp( arg, "allow" ) == 0 )
339                         return ldap_pvt_tls_set_option( lo, option,
340                                 LDAP_OPT_X_TLS_ALLOW );
341                 if ( strcasecmp( arg, "try" ) == 0 )
342                         return ldap_pvt_tls_set_option( lo, option,
343                                 LDAP_OPT_X_TLS_TRY );
344                 if ( strcasecmp( arg, "hard" ) == 0 )
345                         return ldap_pvt_tls_set_option( lo, option,
346                                 LDAP_OPT_X_TLS_HARD );
347                 return -1;
348         default:
349                 return -1;
350         }
351 }
352
353 int
354 ldap_pvt_tls_get_option( struct ldapoptions *lo, int option, void *arg )
355 {
356         switch( option ) {
357         case LDAP_OPT_X_TLS:
358                 *(int *)arg = lo->ldo_tls_mode;
359                 break;
360         case LDAP_OPT_X_TLS_CERT:
361                 if ( lo == NULL )
362                         arg = (void *) tls_def_ctx;
363                 else
364                         arg = lo->ldo_tls_ctx;
365                 break;
366         case LDAP_OPT_X_TLS_CACERTFILE:
367                 *(char **)arg = tls_opt_cacertfile ?
368                         strdup( tls_opt_cacertfile ) : NULL;
369                 break;
370         case LDAP_OPT_X_TLS_CACERTDIR:
371                 *(char **)arg = tls_opt_cacertdir ?
372                         strdup( tls_opt_cacertdir ) : NULL;
373                 break;
374         case LDAP_OPT_X_TLS_CERTFILE:
375                 *(char **)arg = tls_opt_certfile ?
376                         strdup( tls_opt_certfile ) : NULL;
377                 break;
378         case LDAP_OPT_X_TLS_KEYFILE:
379                 *(char **)arg = tls_opt_keyfile ?
380                         strdup( tls_opt_keyfile ) : NULL;
381                 break;
382         case LDAP_OPT_X_TLS_REQUIRE_CERT:
383                 *(int *)arg = tls_opt_require_cert;
384                 break;
385         default:
386                 return -1;
387         }
388         return 0;
389 }
390
391 int
392 ldap_pvt_tls_set_option( struct ldapoptions *lo, int option, void *arg )
393 {
394         switch( option ) {
395         case LDAP_OPT_X_TLS:
396                 switch( *(int *) arg ) {
397                 case LDAP_OPT_X_TLS_NEVER:
398                 case LDAP_OPT_X_TLS_DEMAND:
399                 case LDAP_OPT_X_TLS_ALLOW:
400                 case LDAP_OPT_X_TLS_TRY:
401                 case LDAP_OPT_X_TLS_HARD:
402                         lo->ldo_tls_mode = *(int *)arg;
403                         break;
404                 default:
405                         return -1;
406                 }
407                 break;
408         case LDAP_OPT_X_TLS_CERT:
409                 if ( lo == NULL )
410                         tls_def_ctx = (SSL_CTX *) arg;
411                 else
412                         lo->ldo_tls_ctx = arg;
413                 break;
414         }
415         if ( lo != NULL )
416                 return -1;
417         switch( option ) {
418         case LDAP_OPT_X_TLS_CACERTFILE:
419                 if ( tls_opt_cacertfile ) free( tls_opt_cacertfile );
420                 tls_opt_cacertfile = arg ? strdup( (char *) arg ) : NULL;
421                 break;
422         case LDAP_OPT_X_TLS_CACERTDIR:
423                 if ( tls_opt_cacertdir ) free( tls_opt_cacertdir );
424                 tls_opt_cacertdir = arg ? strdup( (char *) arg ) : NULL;
425                 break;
426         case LDAP_OPT_X_TLS_CERTFILE:
427                 if ( tls_opt_certfile ) free( tls_opt_certfile );
428                 tls_opt_certfile = arg ? strdup( (char *) arg ) : NULL;
429                 break;
430         case LDAP_OPT_X_TLS_KEYFILE:
431                 if ( tls_opt_keyfile ) free( tls_opt_keyfile );
432                 tls_opt_keyfile = arg ? strdup( (char *) arg ) : NULL;
433                 break;
434         case LDAP_OPT_X_TLS_REQUIRE_CERT:
435                 tls_opt_require_cert = * (int *) arg;
436         default:
437                 return -1;
438         }
439         return 0;
440 }
441
442 static int
443 tls_setup( Sockbuf *sb, void *arg )
444 {
445         sb->sb_iodata = arg;
446         return 0;
447 }
448
449 static int
450 tls_remove( Sockbuf *sb )
451 {
452         SSL_free( (SSL *) sb->sb_iodata );
453         return 0;
454 }
455
456 static ber_slen_t
457 tls_write( Sockbuf *sb, void *buf, ber_len_t sz )
458 {
459         int ret = SSL_write( (SSL *)sb->sb_iodata, buf, sz );
460
461         update_flags(sb, (SSL *)sb->sb_iodata );
462         return ret;
463 }
464
465 static ber_slen_t
466 tls_read( Sockbuf *sb, void *buf, ber_len_t sz )
467 {
468         int ret = SSL_read( (SSL *)sb->sb_iodata, buf, sz );
469
470         update_flags(sb, (SSL *)sb->sb_iodata );
471         return ret;
472 }
473
474 static int
475 tls_close( Sockbuf *sb )
476 {
477         tcp_close( ber_pvt_sb_get_desc( sb ) );
478         return 0;
479 }
480
481 static int
482 tls_verify_cb( int ok, X509_STORE_CTX *ctx )
483 {
484         return 1;
485 }
486
487 /* Inspired by ERR_print_errors in OpenSSL */
488 static int
489 tls_report_error( void )
490 {
491         unsigned long l;
492         char buf[200];
493         const char *file;
494         int line;
495
496         while ( ( l = ERR_get_error_line( &file, &line ) ) != 0 ) {
497                         Debug( LDAP_DEBUG_ANY, "TLS: %s %s:%d\n",
498                                ERR_error_string( l, buf ), file, line );
499         }
500 }
501
502 #else
503 static int dummy;
504 #endif