Version reporting & module ABI change.
[exim.git] / src / src / exim.c
index f50a62b944d4d4667e2d0bd9c480bb7d43ceb78f..dd3b5f9e7ecc38ed1932ab81804d5e29886cf295 100644 (file)
@@ -14,6 +14,8 @@ Also a few functions that don't naturally fit elsewhere. */
 
 #include "exim.h"
 
+extern void init_lookup_list(void);
+
 
 
 /*************************************************
@@ -776,53 +778,53 @@ fprintf(f, "Support for:");
 #endif
 fprintf(f, "\n");
 
-fprintf(f, "Lookups:");
-#ifdef LOOKUP_LSEARCH
+fprintf(f, "Lookups (built-in):");
+#if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
   fprintf(f, " lsearch wildlsearch nwildlsearch iplsearch");
 #endif
-#ifdef LOOKUP_CDB
+#if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
   fprintf(f, " cdb");
 #endif
-#ifdef LOOKUP_DBM
+#if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
   fprintf(f, " dbm dbmnz");
 #endif
-#ifdef LOOKUP_DNSDB
+#if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
   fprintf(f, " dnsdb");
 #endif
-#ifdef LOOKUP_DSEARCH
+#if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
   fprintf(f, " dsearch");
 #endif
-#ifdef LOOKUP_IBASE
+#if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
   fprintf(f, " ibase");
 #endif
-#ifdef LOOKUP_LDAP
+#if defined(LOOKUP_LDAP) && LOOKUP_LDAP!=2
   fprintf(f, " ldap ldapdn ldapm");
 #endif
-#ifdef LOOKUP_MYSQL
+#if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
   fprintf(f, " mysql");
 #endif
-#ifdef LOOKUP_NIS
+#if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
   fprintf(f, " nis nis0");
 #endif
-#ifdef LOOKUP_NISPLUS
+#if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
   fprintf(f, " nisplus");
 #endif
-#ifdef LOOKUP_ORACLE
+#if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
   fprintf(f, " oracle");
 #endif
-#ifdef LOOKUP_PASSWD
+#if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
   fprintf(f, " passwd");
 #endif
-#ifdef LOOKUP_PGSQL
+#if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
   fprintf(f, " pgsql");
 #endif
-#ifdef LOOKUP_SQLITE
+#if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
   fprintf(f, " sqlite");
 #endif
-#ifdef LOOKUP_TESTDB
+#if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
   fprintf(f, " testdb");
 #endif
-#ifdef LOOKUP_WHOSON
+#if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
   fprintf(f, " whoson");
 #endif
 fprintf(f, "\n");
@@ -914,6 +916,33 @@ come. */
 #ifdef SUPPORT_TLS
 tls_version_report(f);
 #endif
+
+/* Everything else is details which are only worth reporting when debugging.
+Perhaps the tls_version_report should move into this too. */
+DEBUG(D_any) do {
+
+  int i;
+
+#ifdef AUTH_CYRUS_SASL
+  auth_cyrus_sasl_version_report(f);
+#endif
+
+  fprintf(f, "Library version: PCRE: Compile: %d.%d%s\n"
+             "                       Runtime: %s\n",
+          PCRE_MAJOR, PCRE_MINOR,
+          /* PRE_PRERELEASE is either defined and empty or a string.
+           * This should work: */
+          PCRE_PRERELEASE "",
+          pcre_version());
+
+  init_lookup_list();
+  for (i = 0; i < lookup_list_count; i++)
+    {
+    if (lookup_list[i]->version_report)
+      lookup_list[i]->version_report(f);
+    }
+
+} while (0);
 }
 
 
@@ -1159,6 +1188,21 @@ if (macros == NULL)
 return FALSE;
 #else
 
+/* We only trust -D overrides for some invoking users:
+root, the exim run-time user, the optional config owner user.
+I don't know why config-owner would be needed, but since they can own the
+config files anyway, there's no security risk to letting them override -D. */
+if ( ! ((real_uid == root_uid)
+     || (real_uid == exim_uid)
+#ifdef CONFIGURE_OWNER
+     || (real_uid == config_uid)
+#endif
+   ))
+  {
+  debug_printf("macros_trusted rejecting macros for uid %d\n", (int) real_uid);
+  return FALSE;
+  }
+
 /* Get a list of macros which are whitelisted */
 whitelisted = string_copy_malloc(US WHITELIST_D_MACROS);
 prev_char_item = FALSE;
@@ -1956,13 +2000,17 @@ for (i = 1; i < argc; i++)
       #endif
       if (real_uid != root_uid)
         {
-        #ifdef TRUSTED_CONFIG_PREFIX_LIST
+        #ifdef TRUSTED_CONFIG_LIST
 
-       if (Ustrstr(argrest, "/../"))
+        if (real_uid != exim_uid
+            #ifdef CONFIGURE_OWNER
+            && real_uid != config_uid
+            #endif
+            )
           trusted_config = FALSE;
         else
           {
-          FILE *trust_list = Ufopen(TRUSTED_CONFIG_PREFIX_LIST, "rb");
+          FILE *trust_list = Ufopen(TRUSTED_CONFIG_LIST, "rb");
           if (trust_list)
             {
             struct stat statbuf;
@@ -1988,8 +2036,8 @@ for (i = 1; i < argc; i++)
               {
               /* Well, the trust list at least is up to scratch... */
               void *reset_point = store_get(0);
-              uschar *trusted_prefixes[32];
-              int nr_prefixes = 0;
+              uschar *trusted_configs[32];
+              int nr_configs = 0;
               int i = 0;
 
               while (Ufgets(big_buffer, big_buffer_size, trust_list))
@@ -2002,13 +2050,13 @@ for (i = 1; i < argc; i++)
                 nl = Ustrchr(start, '\n');
                 if (nl)
                   *nl = 0;
-                trusted_prefixes[nr_prefixes++] = string_copy(start);
-                if (nr_prefixes == 32)
+                trusted_configs[nr_configs++] = string_copy(start);
+                if (nr_configs == 32)
                   break;
                 }
               fclose(trust_list);
 
-              if (nr_prefixes)
+              if (nr_configs)
                 {
                 int sep = 0;
                 uschar *list = argrest;
@@ -2016,14 +2064,12 @@ for (i = 1; i < argc; i++)
                 while (trusted_config && (filename = string_nextinlist(&list,
                         &sep, big_buffer, big_buffer_size)) != NULL)
                   {
-                  for (i=0; i < nr_prefixes; i++)
+                  for (i=0; i < nr_configs; i++)
                     {
-                    int len = Ustrlen(trusted_prefixes[i]);
-                    if (Ustrlen(filename) >= len &&
-                        Ustrncmp(filename, trusted_prefixes[i], len) == 0)
+                    if (Ustrcmp(filename, trusted_configs[i]) == 0)
                       break;
                     }
-                  if (i == nr_prefixes)
+                  if (i == nr_configs)
                     {
                     trusted_config = FALSE;
                     break;
@@ -3126,7 +3172,8 @@ if (debug_selector != 0)
     debug_printf("Exim version %s uid=%ld gid=%ld pid=%d D=%x\n",
       version_string, (long int)real_uid, (long int)real_gid, (int)getpid(),
       debug_selector);
-    show_whats_supported(stderr);
+    if (!version_printed)
+      show_whats_supported(stderr);
     }
   }
 
@@ -3468,7 +3515,7 @@ if (removed_privilege && (!trusted_config || macros != NULL) &&
   else
     log_write(0, LOG_MAIN|LOG_PANIC,
       "exim user lost privilege for using %s option",
-      (int)exim_uid, trusted_config? "-D" : "-C");
+      trusted_config? "-D" : "-C");
   }
 
 /* Start up Perl interpreter if Perl support is configured and there is a
@@ -3493,6 +3540,13 @@ if (opt_perl_at_start && opt_perl_startup != NULL)
   }
 #endif /* EXIM_PERL */
 
+/* Initialise lookup_list
+If debugging, already called above via version reporting.
+This does mean that debugging causes the list to be initialised while root.
+This *should* be harmless -- all modules are loaded from a fixed dir and
+it's code that would, if not a module, be part of Exim already. */
+init_lookup_list();
+
 /* Log the arguments of the call if the configuration file said so. This is
 a debugging feature for finding out what arguments certain MUAs actually use.
 Don't attempt it if logging is disabled, or if listing variables or if