agent,dirmngr: Check for homedir removal also using stat(2).
[gnupg.git] / dirmngr / dirmngr_ldap.c
index f166f19..5a9ae97 100644 (file)
@@ -15,7 +15,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
 #endif
 
 #ifdef HAVE_W32_SYSTEM
-#include <winsock2.h>
-#include <winldap.h>
-#include <fcntl.h>
-#include "ldap-url.h"
+# include <winsock2.h>
+# include <winldap.h>
+# include <winber.h>
+# include <fcntl.h>
+# include "ldap-url.h"
 #else
-/* For OpenLDAP, to enable the API that we're using. */
-#define LDAP_DEPRECATED 1
-#include <ldap.h>
+  /* For OpenLDAP, to enable the API that we're using. */
+# define LDAP_DEPRECATED 1
+# include <ldap.h>
 #endif
 
 
-#define JNLIB_NEED_LOG_LOGV
+#include <gpg-error.h>
 #include "../common/logging.h"
 #include "../common/argparse.h"
 #include "../common/stringhelp.h"
 #include "../common/mischelp.h"
 #include "../common/strlist.h"
 
-#include "i18n.h"
-#include "util.h"
+#include "../common/i18n.h"
+#include "../common/util.h"
+#include "../common/init.h"
 
 /* With the ldap wrapper, there is no need for the npth_unprotect and leave
    functions; thus we redefine them to nops.  If we are not using the
@@ -96,6 +98,12 @@ static void npth_protect (void) { }
 # define my_ldap_free_attr(a)           ldap_memfree ((a))
 #endif
 
+#ifdef HAVE_W32_SYSTEM
+ typedef LDAP_TIMEVAL  my_ldap_timeval_t;
+#else
+ typedef struct timeval my_ldap_timeval_t;
+#endif
+
 #define DEFAULT_LDAP_TIMEOUT 100 /* Arbitrary long timeout. */
 
 
@@ -142,7 +150,7 @@ static ARGPARSE_OPTS opts[] = {
   { oAttr,     "attr",      2, N_("|STRING|return the attribute STRING")},
   { oOnlySearchTimeout, "only-search-timeout", 0, "@"},
   { oLogWithPID,"log-with-pid", 0, "@"},
-  { 0, NULL, 0, NULL }
+  ARGPARSE_end ()
 };
 
 
@@ -153,11 +161,11 @@ struct my_opt_s
 {
   int quiet;
   int verbose;
-  struct timeval timeout; /* Timeout for the LDAP search functions.  */
+  my_ldap_timeval_t timeout;/* Timeout for the LDAP search functions.  */
   unsigned int alarm_timeout; /* And for the alarm based timeout.  */
   int multi;
 
-  estream_t outstream;    /* Send output to thsi stream.  */
+  estream_t outstream;    /* Send output to this stream.  */
 
   /* Note that we can't use const for the strings because ldap_* are
      not defined that way.  */
@@ -190,7 +198,7 @@ my_strusage (int level)
 
   switch(level)
     {
-    case 11: p = "dirmngr_ldap (GnuPG)";
+    case 11: p = "dirmngr_ldap (@GNUPG@)";
       break;
     case 13: p = VERSION; break;
     case 17: p = PRINTABLE_OS_NAME; break;
@@ -202,8 +210,8 @@ my_strusage (int level)
       break;
     case 41: p =
           _("Syntax: dirmngr_ldap [options] [URL]\n"
-            "Internal LDAP helper for Dirmngr.\n"
-            "Interface and options may change without notice.\n");
+            "Internal LDAP helper for Dirmngr\n"
+            "Interface and options may change without notice\n");
       break;
 
     default: p = NULL;
@@ -233,9 +241,11 @@ ldap_wrapper_main (char **argv, estream_t outstream)
 
   memset (&my_opt_buffer, 0, sizeof my_opt_buffer);
 
+  early_system_init ();
+
 #ifdef USE_LDAPWRAPPER
   set_strusage (my_strusage);
-  log_set_prefix ("dirmngr_ldap", JNLIB_LOG_WITH_PREFIX);
+  log_set_prefix ("dirmngr_ldap", GPGRT_LOG_WITH_PREFIX);
 
   /* Setup I18N and common subsystems. */
   i18n_init();
@@ -287,7 +297,7 @@ ldap_wrapper_main (char **argv, estream_t outstream)
           {
             unsigned int oldflags;
             log_get_prefix (&oldflags);
-            log_set_prefix (NULL, oldflags | JNLIB_LOG_WITH_PID);
+            log_set_prefix (NULL, oldflags | GPGRT_LOG_WITH_PID);
           }
           break;
 
@@ -400,7 +410,7 @@ print_ldap_entries (my_opt_t myopt, LDAP *ld, LDAPMessage *msg, char *want_attr)
       char *attr;
 
       if (myopt->verbose > 1)
-        log_info (_("scanning result for attribute `%s'\n"),
+        log_info (_("scanning result for attribute '%s'\n"),
                   want_attr? want_attr : "[all]");
 
       if (myopt->multi)
@@ -424,7 +434,7 @@ print_ldap_entries (my_opt_t myopt, LDAP *ld, LDAPMessage *msg, char *want_attr)
           int idx;
 
           if (myopt->verbose > 1)
-            log_info (_("          available attribute `%s'\n"), attr);
+            log_info (_("          available attribute '%s'\n"), attr);
 
           set_timeout (myopt);
 
@@ -462,14 +472,14 @@ print_ldap_entries (my_opt_t myopt, LDAP *ld, LDAPMessage *msg, char *want_attr)
           if (!values)
             {
               if (myopt->verbose)
-                log_info (_("attribute `%s' not found\n"), attr);
+                log_info (_("attribute '%s' not found\n"), attr);
               my_ldap_free_attr (attr);
               continue;
             }
 
           if (myopt->verbose)
             {
-              log_info (_("found attribute `%s'\n"), attr);
+              log_info (_("found attribute '%s'\n"), attr);
               if (myopt->verbose > 1)
                 for (idx=0; values[idx]; idx++)
                   log_info ("         length[%d]=%d\n",
@@ -578,37 +588,37 @@ fetch_ldap (my_opt_t myopt, const char *url, const LDAPURLDesc *ludp)
 
   if (myopt->verbose)
     {
-      log_info (_("processing url `%s'\n"), url);
+      log_info (_("processing url '%s'\n"), url);
       if (myopt->user)
-        log_info (_("          user `%s'\n"), myopt->user);
+        log_info (_("          user '%s'\n"), myopt->user);
       if (myopt->pass)
-        log_info (_("          pass `%s'\n"), *myopt->pass?"*****":"");
+        log_info (_("          pass '%s'\n"), *myopt->pass?"*****":"");
       if (host)
-        log_info (_("          host `%s'\n"), host);
+        log_info (_("          host '%s'\n"), host);
       log_info (_("          port %d\n"), port);
       if (dn)
-        log_info (_("            DN `%s'\n"), dn);
+        log_info (_("            DN '%s'\n"), dn);
       if (filter)
-        log_info (_("        filter `%s'\n"), filter);
+        log_info (_("        filter '%s'\n"), filter);
       if (myopt->multi && !myopt->attr && ludp->lud_attrs)
         {
           int i;
           for (i=0; ludp->lud_attrs[i]; i++)
-            log_info (_("          attr `%s'\n"), ludp->lud_attrs[i]);
+            log_info (_("          attr '%s'\n"), ludp->lud_attrs[i]);
         }
       else if (attr)
-        log_info (_("          attr `%s'\n"), attr);
+        log_info (_("          attr '%s'\n"), attr);
     }
 
 
   if (!host || !*host)
     {
-      log_error (_("no host name in `%s'\n"), url);
+      log_error (_("no host name in '%s'\n"), url);
       return -1;
     }
   if (!myopt->multi && !attr)
     {
-      log_error (_("no attribute given for query `%s'\n"), url);
+      log_error (_("no attribute given for query '%s'\n"), url);
       return -1;
     }
 
@@ -623,7 +633,7 @@ fetch_ldap (my_opt_t myopt, const char *url, const LDAPURLDesc *ludp)
   npth_protect ();
   if (!ld)
     {
-      log_error (_("LDAP init to `%s:%d' failed: %s\n"),
+      log_error (_("LDAP init to '%s:%d' failed: %s\n"),
                  host, port, strerror (errno));
       return -1;
     }
@@ -631,10 +641,23 @@ fetch_ldap (my_opt_t myopt, const char *url, const LDAPURLDesc *ludp)
   /* Fixme:  Can we use MYOPT->user or is it shared with other theeads?.  */
   ret = my_ldap_simple_bind_s (ld, myopt->user, myopt->pass);
   npth_protect ();
+#ifdef LDAP_VERSION3
+  if (ret == LDAP_PROTOCOL_ERROR)
+    {
+      /* Protocol error could mean that the server only supports v3. */
+      int version = LDAP_VERSION3;
+      if (myopt->verbose)
+        log_info ("protocol error; retrying bind with v3 protocol\n");
+      npth_unprotect ();
+      ldap_set_option (ld, LDAP_OPT_PROTOCOL_VERSION, &version);
+      ret = my_ldap_simple_bind_s (ld, myopt->user, myopt->pass);
+      npth_protect ();
+    }
+#endif
   if (ret)
     {
-      log_error (_("binding to `%s:%d' failed: %s\n"),
-                 host, port, strerror (errno));
+      log_error (_("binding to '%s:%d' failed: %s\n"),
+                 host, port, ldap_err2string (ret));
       ldap_unbind (ld);
       return -1;
     }
@@ -658,9 +681,9 @@ fetch_ldap (my_opt_t myopt, const char *url, const LDAPURLDesc *ludp)
   else if (rc)
     {
 #ifdef HAVE_W32CE_SYSTEM
-      log_error ("searching `%s' failed: %d\n", url, rc);
+      log_error ("searching '%s' failed: %d\n", url, rc);
 #else
-      log_error (_("searching `%s' failed: %s\n"),
+      log_error (_("searching '%s' failed: %s\n"),
                  url, ldap_err2string (rc));
 #endif
       if (rc != LDAP_NO_SUCH_OBJECT)
@@ -692,13 +715,13 @@ process_url (my_opt_t myopt, const char *url)
 
   if (!ldap_is_ldap_url (url))
     {
-      log_error (_("`%s' is not an LDAP URL\n"), url);
+      log_error (_("'%s' is not an LDAP URL\n"), url);
       return -1;
     }
 
   if (ldap_url_parse (url, &ludp))
     {
-      log_error (_("`%s' is an invalid LDAP URL\n"), url);
+      log_error (_("'%s' is an invalid LDAP URL\n"), url);
       return -1;
     }