[Date Prev][Date Next] [Chronological] [Thread] [Top]

ITS#4422, #4475, TLS context



We definitely need a more explicit method of manipulating the TLS context for slapd's purposes. E.g., back-ldap, back-meta, and the syncrepl consumer really ought to have a way to specify alternate TLS certificates for their outbound connections. Also, the current implementation is actually broken wrt back-config. That is, slapd.conf/slapd.d parameters get set in a slapd-specific TLS context, which is used for all incoming connections. But back-config doesn't store its own copy of these parameters, it retrieves them using ldap_pvt_tls_get_option() when populating the config entries. The bug here is that there's only the one set of static variables in libldap storing these settings, and anything that was set in ldap.conf will be returned to back-config even though those settings aren't necessarily being used in slapd's TLS context.

I've been tweaking libldap/tls.c toward this goal, but I keep changing my mind about how it should really work. The main point is to push most of these settings into the ldapoptions struct, where they should have been all along. The other problem is that setting the various options has no immediate effect; it's only in the "init_def_ctx" function where they actually get used.

I've moved the body of ldap_pvt_tls_init_def_ctx() into a new function ldap_int_tls_init_ctx() so that it can be used on arbitrary contexts. I think I'm going to add a new tls_set_option to force the context to be initialized. That is, a new SSL_CTX will be allocated and all of the ldo_tls_* options will be pushed into it. At the moment I have no idea what to do about destroying the SSL_CTX when it's no longer needed. Currently we never destroy slapd's private slap_tls_ctx.

The idea so far:
move the tls_def_ctx pointer and the majority of the tls_opt variables into struct ldapoptions. This means the "Default TLS context" is just the value from the LDAP_INT_GLOBAL_OPT() record, and whenever a new LDAP handle is created, it automatically gets a copy of the Default TLS context pointer. Since that's a shared resource, we can't automatically destroy it when the LDAP handle is destroyed. I'm thinking something like this:


#ifdef HAVE_TLS
struct ldaptls {
   void        *lt_ctx;    /* SSL_CTX* */
   LDAP_TLS_CONNECT_CB *lt_connect_cb;
   void        *lt_connect_arg;
   char        *lt_certfile;
   char        *lt_keyfile;
   char        *lt_dhfile;
   char        *lt_cacertfile;
   char        *lt_cacertdir;
   char        *lt_ciphersuite;
   int         lt_require_cert;
#ifdef HAVE_OPENSSL_CRL
   int         lt_crlcheck;
#endif
   int         lt_refcnt;
#ifdef LDAP_R_COMPILE
   ldap_pvt_thread_mutex_t lt_mutex;
#endif
};
#endif

In struct ldapoption:
#ifdef HAVE_TLS
   /* tls context */
   struct ldaptls  *ldo_tls_info;
   int         ldo_tls_mode;
#endif

The refcnt will be used to keep track of when the structure can be freed.

Currently the LDAP_OPT_X_TLS_CTX option gets and sets the SSL_CTX pointer. That's not really useful for slapd, it would be better to get and set the struct ldaptls pointer, which would allow back-config to be accurate in the information it returns.

The code in slapd main.c would change a bit:
   before reading the config:
   ldap_create( &slap_tls_ld );

   processing the config:
   ldap_set_option( slap_tls_ld, LDAP_OPT_X_TLS_ ..., ... );

   after config:
   ldap_set_option( slap_tls_ld, LDAP_OPT_X_TLS_CTX, LDAP_TLS_CTX_INIT );
   ldap_get_option( slap_tls_ld, LDAP_OPT_X_TLS_CTX, &slap_tls_ctx );

LDAP_TLS_CTX_INIT is a magic value (1) to trigger the SSL_CTX initialization, instead of replacing the current context.
At shutdown time we just do an ldap_ld_free( slap_tls_ld ) to destroy all of the context.


The other slapd clients (back-ldap/meta, syncrepl) would inherit whatever ldap.conf settings exist by default, and can then override as above.
ldap_initialize( &myld, uri );


   if ( first_time ) {
       first_time = 0;
       ldap_set_option( myld, LDAP_OPT_X_TLS_ ..., ... );
       ldap_set_option( myld, LDAP_OPT_X_TLS_CTX, LDAP_TLS_CTX_INIT );
       ldap_get_option( myld, LDAP_OPT_X_TLS_CTX, &my_tls_ctx );
   } else {
       ldap_set_option( myld, LDAP_OPT_X_TLS_CTX, my_tls_ctx );
   }

This way each module can fully control the TLS parameters for all of its sessions.

Any suggestions?

--
 -- Howard Chu
 Chief Architect, Symas Corp.  http://www.symas.com
 Director, Highland Sun        http://highlandsun.com/hyc
 OpenLDAP Core Team            http://www.openldap.org/project/