DKIM: reinstate embedded Polarssl SHA routines under older GnuTLS. Bug 1772
[exim.git] / src / src / drtables.c
index 92b4878caa597f3eb4e16c086971f7cfb4c492ea..ec4e72683b243b822fc768b05e972dc180bda4cd 100644 (file)
@@ -1,16 +1,13 @@
-/* $Cambridge: exim/src/src/drtables.c,v 1.11 2009/11/16 19:50:36 nm4 Exp $ */
-
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2009 */
+/* Copyright (c) University of Cambridge 1995 - 2015 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 
 #include "exim.h"
 
-#include <dlfcn.h>
 #include <string.h>
 
 /* This module contains tables that define the lookup methods and drivers
@@ -22,6 +19,8 @@ all described in src/EDITME. */
 lookup_info **lookup_list;
 int lookup_list_count = 0;
 
+static int lookup_list_init_done = 0;
+
 /* Table of information about all possible authentication mechamisms. All
 entries are always present if any mechanism is declared, but the functions are
 set to NULL for those that are not compiled into the binary. */
@@ -38,6 +37,14 @@ set to NULL for those that are not compiled into the binary. */
 #include "auths/dovecot.h"
 #endif
 
+#ifdef AUTH_GSASL
+#include "auths/gsasl_exim.h"
+#endif
+
+#ifdef AUTH_HEIMDAL_GSSAPI
+#include "auths/heimdal_gssapi.h"
+#endif
+
 #ifdef AUTH_PLAINTEXT
 #include "auths/plaintext.h"
 #endif
@@ -46,6 +53,10 @@ set to NULL for those that are not compiled into the binary. */
 #include "auths/spa.h"
 #endif
 
+#ifdef AUTH_TLS
+#include "auths/tls.h"
+#endif
+
 auth_info auths_available[] = {
 
 /* Checking by an expansion condition on plain text */
@@ -59,7 +70,8 @@ auth_info auths_available[] = {
   sizeof(auth_cram_md5_options_block),
   auth_cram_md5_init,                        /* init function */
   auth_cram_md5_server,                      /* server function */
-  auth_cram_md5_client                       /* client function */
+  auth_cram_md5_client,                      /* client function */
+  NULL                                       /* diagnostic function */
   },
 #endif
 
@@ -72,7 +84,8 @@ auth_info auths_available[] = {
   sizeof(auth_cyrus_sasl_options_block),
   auth_cyrus_sasl_init,                      /* init function */
   auth_cyrus_sasl_server,                    /* server function */
-  NULL                                       /* client function */
+  NULL,                                      /* client function */
+  auth_cyrus_sasl_version_report             /* diagnostic function */
   },
 #endif
 
@@ -85,7 +98,36 @@ auth_info auths_available[] = {
   sizeof(auth_dovecot_options_block),
   auth_dovecot_init,                          /* init function */
   auth_dovecot_server,                        /* server function */
-  NULL                                        /* client function */
+  NULL,                                       /* client function */
+  NULL                                        /* diagnostic function */
+  },
+#endif
+
+#ifdef AUTH_GSASL
+  {
+  US"gsasl",                                  /* lookup name */
+  auth_gsasl_options,
+  &auth_gsasl_options_count,
+  &auth_gsasl_option_defaults,
+  sizeof(auth_gsasl_options_block),
+  auth_gsasl_init,                            /* init function */
+  auth_gsasl_server,                          /* server function */
+  NULL,                                       /* client function */
+  auth_gsasl_version_report                   /* diagnostic function */
+  },
+#endif
+
+#ifdef AUTH_HEIMDAL_GSSAPI
+  {
+  US"heimdal_gssapi",                         /* lookup name */
+  auth_heimdal_gssapi_options,
+  &auth_heimdal_gssapi_options_count,
+  &auth_heimdal_gssapi_option_defaults,
+  sizeof(auth_heimdal_gssapi_options_block),
+  auth_heimdal_gssapi_init,                   /* init function */
+  auth_heimdal_gssapi_server,                 /* server function */
+  NULL,                                       /* client function */
+  auth_heimdal_gssapi_version_report          /* diagnostic function */
   },
 #endif
 
@@ -98,7 +140,8 @@ auth_info auths_available[] = {
   sizeof(auth_plaintext_options_block),
   auth_plaintext_init,                       /* init function */
   auth_plaintext_server,                     /* server function */
-  auth_plaintext_client                      /* client function */
+  auth_plaintext_client,                     /* client function */
+  NULL                                       /* diagnostic function */
   },
 #endif
 
@@ -111,11 +154,26 @@ auth_info auths_available[] = {
   sizeof(auth_spa_options_block),
   auth_spa_init,                             /* init function */
   auth_spa_server,                           /* server function */
-  auth_spa_client                            /* client function */
+  auth_spa_client,                           /* client function */
+  NULL                                       /* diagnostic function */
+  },
+#endif
+
+#ifdef AUTH_TLS
+  {
+  US"tls",                                   /* lookup name */
+  auth_tls_options,
+  &auth_tls_options_count,
+  &auth_tls_option_defaults,
+  sizeof(auth_tls_options_block),
+  auth_tls_init,                             /* init function */
+  auth_tls_server,                           /* server function */
+  NULL,                                      /* client function */
+  NULL                                       /* diagnostic function */
   },
 #endif
 
-{ US"", NULL, NULL, NULL, 0, NULL, NULL, NULL  }
+{ US"", NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL  }
 };
 
 
@@ -390,108 +448,162 @@ static void add_lookup_to_list(lookup_info *info)
   lookup_list[pos] = info;
 }
 
+
+/* These need to be at file level for old versions of gcc (2.95.2 reported),
+ * which give parse errors on an extern in function scope.  Each entry needs
+ * to also be invoked in init_lookup_list() below  */
+
+#if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
+extern lookup_module_info whoson_lookup_module_info;
+#endif
+#if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
+extern lookup_module_info testdb_lookup_module_info;
+#endif
+#if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
+extern lookup_module_info sqlite_lookup_module_info;
+#endif
+#ifdef EXPERIMENTAL_SPF
+extern lookup_module_info spf_lookup_module_info;
+#endif
+#if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
+extern lookup_module_info pgsql_lookup_module_info;
+#endif
+#if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
+extern lookup_module_info passwd_lookup_module_info;
+#endif
+#if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
+extern lookup_module_info redis_lookup_module_info;
+#endif
+#if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
+extern lookup_module_info oracle_lookup_module_info;
+#endif
+#if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
+extern lookup_module_info nisplus_lookup_module_info;
+#endif
+#if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
+extern lookup_module_info nis_lookup_module_info;
+#endif
+#if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
+extern lookup_module_info mysql_lookup_module_info;
+#endif
+#if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
+extern lookup_module_info lsearch_lookup_module_info;
+#endif
+#ifdef LOOKUP_LDAP
+extern lookup_module_info ldap_lookup_module_info;
+#endif
+#if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
+extern lookup_module_info ibase_lookup_module_info;
+#endif
+#if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
+extern lookup_module_info dsearch_lookup_module_info;
+#endif
+#if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
+extern lookup_module_info dnsdb_lookup_module_info;
+#endif
+#if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
+extern lookup_module_info dbmdb_lookup_module_info;
+#endif
+#if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
+extern lookup_module_info cdb_lookup_module_info;
+#endif
+
 void init_lookup_list(void)
 {
+#ifdef LOOKUP_MODULE_DIR
   DIR *dd;
   struct dirent *ent;
-  const pcre *regex_islookupmod = regex_must_compile(US"\\.so$", FALSE, TRUE);
   int countmodules = 0;
   int moduleerrors = 0;
+#endif
   struct lookupmodulestr *p;
+  const pcre *regex_islookupmod = regex_must_compile(
+      US"\\." DYNLIB_FN_EXT "$", FALSE, TRUE);
+
+  if (lookup_list_init_done)
+    return;
+  lookup_list_init_done = 1;
 
 #if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
-extern lookup_module_info cdb_lookup_module_info;
   addlookupmodule(NULL, &cdb_lookup_module_info);
 #endif
 
 #if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
-extern lookup_module_info dbmdb_lookup_module_info;
   addlookupmodule(NULL, &dbmdb_lookup_module_info);
 #endif
 
 #if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
-extern lookup_module_info dnsdb_lookup_module_info;
   addlookupmodule(NULL, &dnsdb_lookup_module_info);
 #endif
 
 #if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
-extern lookup_module_info dsearch_lookup_module_info;
   addlookupmodule(NULL, &dsearch_lookup_module_info);
 #endif
 
 #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
-extern lookup_module_info ibase_lookup_module_info;
   addlookupmodule(NULL, &ibase_lookup_module_info);
 #endif
 
 #ifdef LOOKUP_LDAP
-extern lookup_module_info ldap_lookup_module_info;
   addlookupmodule(NULL, &ldap_lookup_module_info);
 #endif
 
 #if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
-extern lookup_module_info lsearch_lookup_module_info;
   addlookupmodule(NULL, &lsearch_lookup_module_info);
 #endif
 
 #if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
-extern lookup_module_info mysql_lookup_module_info;
   addlookupmodule(NULL, &mysql_lookup_module_info);
 #endif
 
 #if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
-extern lookup_module_info nis_lookup_module_info;
   addlookupmodule(NULL, &nis_lookup_module_info);
 #endif
 
 #if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
-extern lookup_module_info nisplus_lookup_module_info;
   addlookupmodule(NULL, &nisplus_lookup_module_info);
 #endif
 
 #if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
-extern lookup_module_info oracle_lookup_module_info;
   addlookupmodule(NULL, &oracle_lookup_module_info);
 #endif
 
 #if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
-extern lookup_module_info passwd_lookup_module_info;
   addlookupmodule(NULL, &passwd_lookup_module_info);
 #endif
 
 #if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
-extern lookup_module_info pgsql_lookup_module_info;
   addlookupmodule(NULL, &pgsql_lookup_module_info);
 #endif
 
+#if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
+  addlookupmodule(NULL, &redis_lookup_module_info);
+#endif
+
 #ifdef EXPERIMENTAL_SPF
-extern lookup_module_info spf_lookup_module_info;
   addlookupmodule(NULL, &spf_lookup_module_info);
 #endif
 
 #if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
-extern lookup_module_info sqlite_lookup_module_info;
   addlookupmodule(NULL, &sqlite_lookup_module_info);
 #endif
 
 #if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
-extern lookup_module_info testdb_lookup_module_info;
   addlookupmodule(NULL, &testdb_lookup_module_info);
 #endif
 
 #if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
-extern lookup_module_info whoson_lookup_module_info;
   addlookupmodule(NULL, &whoson_lookup_module_info);
 #endif
 
 #ifdef LOOKUP_MODULE_DIR
   dd = opendir(LOOKUP_MODULE_DIR);
   if (dd == NULL) {
-    DEBUG(5) debug_printf("Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
+    DEBUG(D_lookup) debug_printf("Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
     log_write(0, LOG_MAIN, "Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
   }
   else {
-    DEBUG(9) debug_printf("Loading lookup modules from %s\n", LOOKUP_MODULE_DIR);
+    DEBUG(D_lookup) debug_printf("Loading lookup modules from %s\n", LOOKUP_MODULE_DIR);
     while ((ent = readdir(dd)) != NULL) {
       char *name = ent->d_name;
       int len = (int)strlen(name);
@@ -499,7 +611,7 @@ extern lookup_module_info whoson_lookup_module_info;
         int pathnamelen = len + (int)strlen(LOOKUP_MODULE_DIR) + 2;
         void *dl;
         struct lookup_module_info *info;
-        char *errormsg;
+        const char *errormsg;
 
         /* SRH: am I being paranoid here or what? */
         if (pathnamelen > big_buffer_size) {
@@ -519,6 +631,13 @@ extern lookup_module_info whoson_lookup_module_info;
           continue;
         }
 
+        /* FreeBSD nsdispatch() can trigger dlerror() errors about
+         * _nss_cache_cycle_prevention_function; we need to clear the dlerror()
+         * state before calling dlsym(), so that any error afterwards only
+         * comes from dlsym().
+         */
+        errormsg = dlerror();
+
         info = (struct lookup_module_info*) dlsym(dl, "_lookup_module_info");
         if ((errormsg = dlerror()) != NULL) {
           fprintf(stderr, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
@@ -536,19 +655,19 @@ extern lookup_module_info whoson_lookup_module_info;
         }
 
         addlookupmodule(dl, info);
-        DEBUG(9) debug_printf("Loaded \"%s\" (%d lookup types)\n", name, info->lookupcount);
+        DEBUG(D_lookup) debug_printf("Loaded \"%s\" (%d lookup types)\n", name, info->lookupcount);
         countmodules++;
       }
     }
     closedir(dd);
   }
 
-  DEBUG(9) debug_printf("Loaded %d lookup modules\n", countmodules);
+  DEBUG(D_lookup) debug_printf("Loaded %d lookup modules\n", countmodules);
 #endif
 
   store_free((void*)regex_islookupmod);
 
-  DEBUG(4) debug_printf("Total %d lookups\n", lookup_list_count);
+  DEBUG(D_lookup) debug_printf("Total %d lookups\n", lookup_list_count);
 
   lookup_list = store_malloc(sizeof(lookup_info *) * lookup_list_count);
   memset(lookup_list, 0, sizeof(lookup_info *) * lookup_list_count);