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