]> Pileus Git - ~andy/fetchmail/commitdiff
Merge branch '4-integration-retrieve-error-policy' into next
authorMatthias Andree <matthias.andree@gmx.de>
Tue, 14 Dec 2010 16:26:36 +0000 (17:26 +0100)
committerMatthias Andree <matthias.andree@gmx.de>
Tue, 14 Dec 2010 16:26:36 +0000 (17:26 +0100)
Makefile.am
NEWS
README.PWMD [new file with mode: 0644]
configure.ac
fetchmail.c
fetchmail.h
fm_md5.h
options.c
rcfile_l.l
rcfile_y.y

index 4013ad0ec3f1d5532afa0573bfc8978cd0e994ba..7213254de50c6acee0f70520c21d452e7faef77a 100644 (file)
@@ -16,6 +16,11 @@ dist_man1_MANS=              fetchmail.man
 pys=                   fetchmailconf.py
 pym=                   fetchmailconf.man
 
+if HAVE_LIBPWMD
+CFLAGS += @libpwmd_CFLAGS@
+LDFLAGS += @libpwmd_LIBS@
+endif
+
 if HAVE_PYTHON
 nodist_bin_SCRIPTS=    fetchmailconf
 python_PYTHON=         $(pys)
@@ -39,7 +44,7 @@ libfm_a_SOURCES=      xmalloc.c base64.c rfc822.c report.c rfc2047e.c \
                        libesmtp/gethostbyname.h libesmtp/gethostbyname.c \
                        smbtypes.h fm_getaddrinfo.c tls.c rfc822valid.c \
                        xmalloc.h sdump.h sdump.c x509_name_match.c \
-                       fm_strl.h
+                       fm_strl.h md5c.c
 if NTLM_ENABLE
 libfm_a_SOURCES += ntlmsubr.c
 endif
diff --git a/NEWS b/NEWS
index 3144f0ec0f99871bf8fb39b71da48ea942f00b4c..3947f17482e43b68822079c1d0dcfe54d458f4f9 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -49,7 +49,11 @@ NOTE THIS IS AN ALPHA RELEASE THAT HAS NOT BEEN THOROUGHLY TESTED!
 # MAJOR CHANGES
 * The UIDL handler code is now much faster, especially noticable with lots of
   mail kept on a POP3 server. Where the 6.3.X code was of O(n^2) complexity,
-  we're down to O(n log n).  (Rainer Weikusat, MAD Partners Ltd./MSS GmbH).
+  we're down to O(n log n).
+  Contributed by Rainer Weikusat, MAD Partners Ltd./MSS GmbH.
+* Fetchmail can now retrieve credentials from PWMD. This needs to be enabled at
+  compile-time and requires run-time configuration. See README.PWMD for details.
+  Contributed by Ben Kibbey, author of libpwmd and pwmd.
 
 # REMOVED FEATURES
 * POP2 and RPOP were long obsolete and removed
@@ -65,7 +69,12 @@ NOTE THIS IS AN ALPHA RELEASE THAT HAS NOT BEEN THOROUGHLY TESTED!
 
 --------------------------------------------------------------------------------
 
-not yet released:
+fetchmail-6.3.20 (not yet released):
+
+# CHANGES
+* fetchmail now always uses its own MD5 implementation.  The library and header
+  variants are too diverse, and we've been bitten before -- and configure
+  complains noisily on Cyrus-SASL's RFC1321 md5.h.
 
 # TRANSLATION UPDATES
   [ja]    Japanese (Takeshi Hamasaki)
diff --git a/README.PWMD b/README.PWMD
new file mode 100644 (file)
index 0000000..13cbb2b
--- /dev/null
@@ -0,0 +1,82 @@
+When compiled with pwmd (Password Manager Daemon) support (--enable-pwmd)
+fetchmail can retrieve server details from pwmd. pwmd v2.0 and libpwmd v6.0.0
+or later are required.
+
+Three new configuration parameters are added: pwmd_socket (optional) to
+specify the socket to connect to (default is ~/.pwmd/socket), pwmd_file
+(required) which specifies the filename on the server to open, and a global
+parameter pinentry_timeout (optional) which specifies the number of seconds
+until pinentry is cancelled while waiting for the password.
+
+Three new command line options are also added:
+    --pwmd-socket, -C     same as pwmd_socket
+    --pwmd-file, -G       same as pwmd_file
+    --pinentry_timeout, -O same as pinentry_timeout
+
+If no pinentry timeout value is specified then the server default will be
+used.
+
+The format of pwmd_socket and --pwmd-socket can be either a URL string in the
+form of:
+       file://[path/to/socket]
+
+       or
+
+       ssh[46]://[username@]hostname[:port],identity_file,known_hosts_file
+
+If neither file:// or ssh[46]:// are specified it is assumed to be a local
+UNIX domain socket to connect to (file://~/.pwmd/socket).
+
+See the pwmc(1) manual page for details about the identity and known_hosts
+files. Note that if connecting to a remote pwmd server, pwmd's pinentry will
+be disabled and a local pinentry will be tried.
+
+The data that pwmd uses to serve clients is stored in an (encrypted) XML file.
+You'll need to create the file you want fetchmail to use by connecting to the
+server with a pwmd client (socat or pwmc from libpwmd) and send commands to
+store the data. See COMMANDS included with pwmd for details.
+
+The password, if any, to open the encrypted data file is either cached on the
+server (the file has been opened before), or gotten from pinentry(1). See the
+pwmd(1) manual page for information about the ~/.pwmd/pinentry.conf file which
+may contain DISPLAY and TTYNAME settings to let pinentry(1) know where to
+prompt for the password.
+
+An account (e.g., pollname) may be an element path. Instead of separating the
+elements with a TAB character, separate them with a '^'.
+
+Here are the elements that fetchmail uses:
+
+    [...]elements in the element path (^ separated)[...]
+    <pollname>
+       <username>              - Optional (--username/username)
+       <password>              - Optional (--password/password)
+       <POP3|IMAP|etc..>       - Server protocol (must match the protocol
+                                 keyword from the rcfile or command line)
+           <hostname>          - Required (servername/via)
+           <port>              - Required (--service/protocol)
+           <ssl>               - Optional (--ssl/ssl)
+           <sslfingerprint>    - Optional (--sslfingerprint/sslfingerprint)
+       </POP3|IMAP|etc..>
+    </pollname>
+
+
+A minimal fetchmailrc might look like this:
+
+    set pinentry_timeout 30
+    poll isp proto POP3:
+       pwmd_file default
+
+    poll myaccounts^isp proto IMAP:
+       pwmd_file default
+       pwmd_socket "ssh://user@host,~/.pwmd/fetchmail,~/.pwmd/known_hosts"
+
+
+Or from the command line:
+
+    fetchmail -f fetchmailrc isp
+    fetchmail --pwmd-file somefile -p POP3 isp
+
+
+Ben Kibbey <bjk@luxsci.net>
+http://bjk.sourceforge.net/pwmd/.
index 73aeece781da8aac5fce2a34820f74dd72df0334..64277f165237b6e430a098d7e1b4d23dc3cefb81 100644 (file)
@@ -58,8 +58,7 @@ if test "x$SHELL" = "x" ; then
     AC_MSG_ERROR(no SUS compliant shell found - on Solaris, install SUNWxcu4)
 fi
 
-
-AC_CHECK_HEADERS([arpa/nameser.h md5.h])
+AC_CHECK_HEADERS([arpa/nameser.h])
 
 AC_CHECK_HEADERS([resolv.h],,,[
 #include <sys/types.h>
@@ -110,16 +109,6 @@ AC_CHECK_FUNC(inet_addr,
 
 AC_REPLACE_FUNCS([stpcpy strlcpy strlcat])
 
-have_md5=no
-if test "$ac_cv_header_md5_h" != no ; then
-    AC_SEARCH_LIBS(MD5Init, [md], [have_md5=yes])
-fi
-
-if test "$have_md5" != yes ; then
-    AC_LIBSOURCE(md5c.c)
-    EXTRAOBJ="$EXTRAOBJ md5c.\$(OBJEXT)"
-fi
-
 AC_CHECK_FUNC(getopt_long, [],
               [AC_LIBSOURCES([getopt.c, getopt1.c])
               EXTRAOBJ="$EXTRAOBJ getopt.\$(OBJEXT) getopt1.\$(OBJEXT)"])
@@ -186,6 +175,22 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <signal.h>
 
 AC_DEFINE_UNQUOTED(PID_DIR, "/var/run", directory for PID lock files)
 
+AC_ARG_ENABLE(pwmd,
+       [  --enable-pwmd           enable Password Manager Daemon support],
+       , [enable_pwmd=no])
+
+if test "$enable_pwmd" = "yes"; then
+    PKG_CHECK_EXISTS([libpwmd], have_libpwmd=1,
+                    AC_MSG_ERROR([Could not find libpwmd pkg-config module.]))
+
+
+    PKG_CHECK_MODULES([libpwmd], [libpwmd >= 6.0.0])
+    AM_CONDITIONAL(HAVE_LIBPWMD, true)
+    AC_DEFINE(HAVE_LIBPWMD, 1, [Define if you have libPWMD installed.])
+else
+    AM_CONDITIONAL(HAVE_LIBPWMD, false)
+fi
+
 # We may have a fallback MDA available in case the socket open to the 
 # local SMTP listener fails.  Best to use procmail for this, as we know
 # it won't try delivering through local SMTP and cause a mail loop.
index d83da942349030b5847c13a7aa0367d2f5ed53f3..c99468f868b0f33deb89185585c973b2fce4ebda 100644 (file)
@@ -77,6 +77,12 @@ static time_t parsetime;     /* time of last parse */
 static void terminate_run(int);
 static void terminate_poll(int);
 
+#ifdef HAVE_LIBPWMD
+static pwm_t *pwm;             /* the handle */
+static const char *pwmd_socket;        /* current socket */
+static const char *pwmd_file;  /* current file */
+#endif
+
 #if defined(__FreeBSD__) && defined(__FreeBSD_USE_KVM)
 /* drop SGID kmem privileage until we need it */
 static void dropprivs(void)
@@ -141,6 +147,282 @@ static void printcopyright(FILE *fp) {
 
 const char *iana_charset;
 
+#ifdef HAVE_LIBPWMD
+static void exit_with_pwmd_error(gpg_error_t error)
+{
+    gpg_err_code_t code = gpg_err_code(error);
+
+    report(stderr, GT_("pwmd: error %i: %s\n"), code, pwmd_strerror(error));
+
+    if (pwm) {
+       pwmd_close(pwm);
+       pwm = NULL;
+    }
+
+    /* Don't exit if daemonized. There may be other active accounts. */
+    if (isatty(1))
+       exit(PS_UNDEFINED);
+}
+
+static int do_pwmd_connect(const char *socketname, const char *filename)
+{
+    static int init;
+    gpg_error_t rc;
+    pwmd_socket_t s;
+
+    if (!init) {
+       pwmd_init();
+       init = 1;
+    }
+
+    if (!pwm || (pwm && socketname && !pwmd_socket) ||
+           (pwm && !socketname && pwmd_socket) ||
+           (pwm && socketname && pwmd_socket && strcmp(socketname, pwmd_socket))) {
+       if (pwm)
+           pwmd_close(pwm);
+
+       pwm = pwmd_new("Fetchmail");
+       rc = pwmd_connect_url(pwm, socketname);
+
+       if (rc) {
+           exit_with_pwmd_error(rc);
+           return 1;
+       }
+    }
+
+    if (run.pinentry_timeout > 0) {
+       rc = pwmd_setopt(pwm, PWMD_OPTION_PINENTRY_TIMEOUT,
+               run.pinentry_timeout);
+
+       if (rc) {
+           exit_with_pwmd_error(rc);
+           return 1;
+       }
+    }
+
+    rc = pwmd_socket_type(pwm, &s);
+
+    if (rc) {
+       exit_with_pwmd_error(rc);
+       return 1;
+    }
+
+    if (!pwmd_file || strcmp(filename, pwmd_file)) {
+       if (s == PWMD_SOCKET_SSH)
+           /* use a local pinentry since X11 forwarding is broken. */
+           rc = pwmd_open2(pwm, filename);
+       else
+           rc = pwmd_open(pwm, filename);
+
+       if (rc) {
+           exit_with_pwmd_error(rc);
+           return 1;
+       }
+    }
+
+    /* May be null to use the default of ~/.pwmd/socket. */
+    pwmd_socket = socketname;
+    pwmd_file = filename;
+    return 0;
+}
+
+static int get_pwmd_details(const char *pwmd_account, int protocol,
+       struct query *ctl)
+{
+    const char *prot = showproto(protocol);
+    gpg_error_t error;
+    char *result;
+    char *tmp = xstrdup(pwmd_account);
+    int i;
+
+    for (i = 0; tmp[i]; i++) {
+       if (i && tmp[i] == '^')
+           tmp[i] = '\t';
+    }
+
+    /*
+     * Get the hostname for this protocol. Element path must be
+     * account->[protocol]->hostname.
+     */
+    error = pwmd_command(pwm, &result, "GET %s\t%s\thostname", tmp, prot);
+
+    if (error) {
+       if (gpg_err_code(error) == GPG_ERR_NOT_FOUND) {
+           report(stderr, GT_("pwmd: %s->%s->hostname: %s\n"), pwmd_account, prot, pwmd_strerror(error));
+           pwmd_close(pwm);
+           pwm = NULL;
+
+           if (isatty(1))
+               exit(PS_SYNTAX);
+
+           return 1;
+       }
+       else {
+           exit_with_pwmd_error(error);
+           return 1;
+       }
+    }
+
+    if (ctl->server.pollname != ctl->server.via)
+       xfree(ctl->server.via);
+
+    ctl->server.via = xstrdup(result);
+
+    if (ctl->server.queryname)
+       xfree(ctl->server.queryname);
+
+    ctl->server.queryname = xstrdup(ctl->server.via);
+
+    if (ctl->server.truename)
+       xfree(ctl->server.truename);
+
+    ctl->server.truename = xstrdup(ctl->server.queryname);
+    pwmd_free(result);
+
+    /*
+     * Server port. Fetchmail tries standard ports for known services so it
+     * should be alright if this element isn't found. ctl->server.protocol is
+     * already set. This sets ctl->server.service.
+     */
+    error = pwmd_command(pwm, &result, "GET %s\t%s\tport", tmp, prot);
+
+    if (error) {
+       if (gpg_err_code(error) == GPG_ERR_NOT_FOUND)
+           report(stderr, GT_("pwmd: %s->%s->port: %s\n"), pwmd_account, prot, pwmd_strerror(error));
+       else {
+           exit_with_pwmd_error(error);
+           return 1;
+       }
+    }
+    else {
+       if (ctl->server.service)
+           xfree(ctl->server.service);
+
+       ctl->server.service = xstrdup(result);
+       pwmd_free(result);
+    }
+
+    /*
+     * Get the remote username. Element must be account->username.
+     */
+    error = pwmd_command(pwm, &result, "GET %s\tusername", tmp);
+
+    if (error) {
+       if (gpg_err_code(error) == GPG_ERR_NOT_FOUND) {
+           report(stderr, GT_("pwmd: %s->username: %s\n"), pwmd_account, pwmd_strerror(error));
+
+           if (!isatty(1)) {
+               pwmd_close(pwm);
+               pwm = NULL;
+               return 1;
+           }
+       }
+       else {
+           exit_with_pwmd_error(error);
+           return 1;
+       }
+    }
+    else {
+       if (ctl->remotename)
+           xfree(ctl->remotename);
+
+       if (ctl->server.esmtp_name)
+           xfree(ctl->server.esmtp_name);
+
+       ctl->remotename = xstrdup(result);
+       ctl->server.esmtp_name = xstrdup(result);
+       pwmd_free(result);
+    }
+
+    /*
+     * Get the remote password. Element must be account->password.
+     */
+    error = pwmd_command(pwm, &result, "GET %s\tpassword", tmp);
+
+    if (error) {
+       if (gpg_err_code(error) == GPG_ERR_NOT_FOUND) {
+           report(stderr, GT_("pwmd: %s->password: %s\n"), pwmd_account, pwmd_strerror(error));
+
+           if (!isatty(1)) {
+               pwmd_close(pwm);
+               pwm = NULL;
+               return 1;
+           }
+       }
+       else {
+           exit_with_pwmd_error(error);
+           return 1;
+       }
+    }
+    else {
+       if (ctl->password)
+           xfree(ctl->password);
+
+       ctl->password= xstrdup(result);
+       pwmd_free(result);
+    }
+
+#ifdef SSL_ENABLE
+    /*
+     * If there is a ssl element and set to 1, enable ssl for this account.
+     * Element path must be account->[protocol]->ssl.
+     */
+    error = pwmd_command(pwm, &result, "GET %s\t%s\tssl", tmp, prot);
+
+    if (error) {
+       if (gpg_err_code(error) == GPG_ERR_NOT_FOUND) {
+           report(stderr, GT_("pwmd: %s->%s->ssl: %s\n"), pwmd_account, prot, pwmd_strerror(error));
+
+           if (!isatty(1)) {
+               pwmd_close(pwm);
+               pwm = NULL;
+               return 1;
+           }
+       }
+       else {
+           exit_with_pwmd_error(error);
+           return 1;
+       }
+    }
+    else {
+       ctl->use_ssl = atoi(result) >= 1 ? FLAG_TRUE : FLAG_FALSE;
+       pwmd_free(result);
+    }
+
+    /*
+     * account->[protocol]->sslfingerprint.
+     */
+    error = pwmd_command(pwm, &result, "GET %s\t%s\tsslfingerprint", tmp, prot);
+
+    if (error) {
+       if (gpg_err_code(error) == GPG_ERR_NOT_FOUND) {
+           report(stderr, GT_("pwmd: %s->%s->sslfingerprint: %s\n"), pwmd_account, prot, pwmd_strerror(error));
+
+           if (!isatty(1)) {
+               pwmd_close(pwm);
+               pwm = NULL;
+               return 1;
+           }
+       }
+       else {
+           exit_with_pwmd_error(error);
+           return 1;
+       }
+    }
+    else {
+       if (ctl->sslfingerprint)
+           xfree(ctl->sslfingerprint);
+
+       ctl->sslfingerprint = xstrdup(result);
+       pwmd_free(result);
+    }
+#endif
+
+    xfree(tmp);
+    return 0;
+}
+#endif
+
 int main(int argc, char **argv)
 {
     int bkgd = FALSE;
@@ -265,6 +547,9 @@ int main(int argc, char **argv)
 #ifdef KERBEROS_V5
        "+KRB5"
 #endif /* KERBEROS_V5 */
+#ifdef HAVE_LIBPWMD
+       "+PWMD"
+#endif /* HAVE_LIBPWMD */
        ".\n";
        printf(GT_("This is fetchmail release %s"), VERSION);
        fputs(features, stdout);
@@ -615,6 +900,11 @@ int main(int argc, char **argv)
         * leaks...
         */
        struct stat     rcstat;
+#ifdef HAVE_LIBPWMD
+       time_t now;
+
+       time(&now);
+#endif
 
        if (strcmp(rcfile, "-") == 0) {
            /* do nothing */
@@ -624,7 +914,15 @@ int main(int argc, char **argv)
                       GT_("couldn't time-check %s (error %d)\n"),
                       rcfile, errno);
        }
+#ifdef HAVE_LIBPWMD
+       /*
+        * isatty() to make sure this is a background process since the
+        * lockfile is removed after each invokation.
+        */
+       else if (!isatty(1) && rcstat.st_mtime > parsetime)
+#else
        else if (rcstat.st_mtime > parsetime)
+#endif
        {
            report(stdout, GT_("restarting fetchmail (%s changed)\n"), rcfile);
 
@@ -717,6 +1015,19 @@ int main(int argc, char **argv)
 
                    dofastuidl = 0; /* this is reset in the driver if required */
 
+#ifdef HAVE_LIBPWMD
+                   /*
+                    * At each poll interval, check the pwmd server for
+                    * changes in host and auth settings.
+                    */
+                   if (ctl->pwmd_file) {
+                       if (do_pwmd_connect(ctl->pwmd_socket, ctl->pwmd_file))
+                           continue;
+
+                       if (get_pwmd_details(ctl->server.pollname, ctl->server.protocol, ctl))
+                           continue;
+                   }
+#endif
                    querystatus = query_host(ctl);
 
                    if (NUM_NONZERO(ctl->fastuidl))
@@ -785,6 +1096,13 @@ int main(int argc, char **argv)
                }
            }
 
+#ifdef HAVE_LIBPWMD
+       if (pwm) {
+           pwmd_close(pwm);
+           pwm = NULL;
+       }
+#endif
+
        /* close connections cleanly */
        terminate_poll(0);
 
@@ -1031,8 +1349,36 @@ static int load_params(int argc, char **argv, int optind)
 
     if ((implicitmode = (optind >= argc)))
     {
+#ifdef HAVE_LIBPWMD
+       for (ctl = querylist; ctl; ctl = ctl->next) {
+           ctl->active = !ctl->server.skip;
+
+           if (ctl->pwmd_file) {
+               /*
+                * Cannot get an element path without a service.
+                */
+               if (ctl->server.protocol <= 1) {
+                   report(stderr, GT_("fetchmail: %s configuration invalid, pwmd_file requires a protocol specification\n"),
+                           ctl->server.pollname);
+                   pwmd_close(pwm);
+                   exit(PS_SYNTAX);
+               }
+
+               if (do_pwmd_connect(ctl->pwmd_socket, ctl->pwmd_file))
+                   continue;
+
+               if (get_pwmd_details(ctl->server.pollname, ctl->server.protocol,
+                           ctl))
+                   continue;
+
+               time(&rcstat.st_mtime);
+           }
+       }
+
+#else
        for (ctl = querylist; ctl; ctl = ctl->next)
            ctl->active = !ctl->server.skip;
+#endif
     }
     else
        for (; optind < argc; optind++) 
@@ -1053,6 +1399,27 @@ static int load_params(int argc, char **argv, int optind)
                        fprintf(stderr,GT_("Warning: multiple mentions of host %s in config file\n"),argv[optind]);
                    ctl->active = TRUE;
                    predeclared = TRUE;
+
+#ifdef HAVE_LIBPWMD
+                   if (ctl->pwmd_file) {
+                       /*
+                        * Cannot get an element path without a service.
+                        */
+                       if (ctl->server.protocol <= 1) {
+                           report(stderr, GT_("%s configuration invalid, pwmd_file requires a protocol specification\n"),
+                                  ctl->server.pollname);
+                           exit(PS_SYNTAX);
+                       }
+
+                       fprintf(stderr, "%s(%i): %s\n", __FILE__, __LINE__, __FUNCTION__);
+                       if (do_pwmd_connect(ctl->pwmd_socket, ctl->pwmd_file))
+                           continue;
+
+                       if (get_pwmd_details(ctl->server.pollname,
+                                   ctl->server.protocol, ctl))
+                           continue;
+                   }
+#endif
                }
 
            if (!predeclared)
@@ -1063,8 +1430,32 @@ static int load_params(int argc, char **argv, int optind)
                 * call later on.
                 */
                ctl = hostalloc((struct query *)NULL);
+
+#ifdef HAVE_LIBPWMD
+               if (cmd_opts.pwmd_file) {
+                   /*
+                    * Cannot get an element path without a service.
+                    */
+                   if (cmd_opts.server.protocol == 0 || cmd_opts.server.protocol == 1) {
+                       report(stderr, GT_("Option --pwmd-file needs a service (-p) parameter.\n"));
+                       exit(PS_SYNTAX);
+                   }
+
+                       fprintf(stderr, "%s(%i): %s\n", __FILE__, __LINE__, __FUNCTION__);
+                   if (do_pwmd_connect(cmd_opts.pwmd_socket, cmd_opts.pwmd_file))
+                       continue;
+
+                   if (get_pwmd_details(argv[optind], cmd_opts.server.protocol,
+                           ctl))
+                       continue;
+               }
+               else
+                   ctl->server.via =
+                       ctl->server.pollname = xstrdup(argv[optind]);
+#else
                ctl->server.via =
                    ctl->server.pollname = xstrdup(argv[optind]);
+#endif
                ctl->active = TRUE;
                ctl->server.lead_server = (struct hostdata *)NULL;
            }
index 8cda2b3af2b238741f19979f3fe17393e8e46992..a1048dc8bff2a35641c5e8fe1c92569475d2fc1a 100644 (file)
@@ -27,6 +27,10 @@ struct addrinfo;
 
 #include "uid_db.h"
 
+#ifdef HAVE_LIBPWMD
+#include <libpwmd.h>
+#endif
+
 /* constants designating the various supported protocols */
 #define                P_AUTO          1
 #define                P_POP3          3
@@ -157,6 +161,9 @@ struct runctl
     char       *pidfile;       /** where to record the PID of daemon mode processes */
     const char *postmaster;
     char       *properties;
+#ifdef HAVE_LIBPWMD
+    int                pinentry_timeout;
+#endif
     int                poll_interval;  /** poll interval in seconds (daemon mode, 0 == off) */
     flag       bouncemail;
     flag       spambounce;
@@ -246,7 +253,7 @@ struct hostdata             /* shared among all user connections to given server */
     struct idlist *akalist;            /* server name first, then akas */
     struct idlist *localdomains;       /* list of pass-through domains */
     int protocol;                      /* protocol type */
-    const char *service;               /* service name */
+    char *service;                     /* service name */
     int interval;                      /* # cycles to skip between polls */
     int authenticate;                  /* authentication mode to try */
     int timeout;                       /* inactivity timout in seconds */
@@ -310,6 +317,11 @@ struct query
     char *password;            /* remote password to use */
     struct idlist *mailboxes;  /* list of mailboxes to check */
 
+#ifdef HAVE_LIBPWMD
+    char *pwmd_socket;         /* socket to connect to */
+    char *pwmd_file;           /* file to open on the server */
+#endif
+
     /* per-forwarding-target data */
     struct idlist *smtphunt;   /* list of SMTP hosts to try forwarding to */
     struct idlist *domainlist; /* domainlist to fetch from */
index a92a3988260097e58e9aec2695c2d91ea541c7c8..cc1a96878e86b2a67d54df6f92a75d44e0c6805c 100644 (file)
--- a/fm_md5.h
+++ b/fm_md5.h
@@ -23,7 +23,7 @@ struct MD5Context {
 void MD5Init(struct MD5Context *context);
 void MD5Update(struct MD5Context *context, const void *buf, unsigned len);
 void MD5Final(void *digest, struct MD5Context *context);
-void MD5Transform(uint32_t buf[], uint32_t const in[]);
+void MD5Transform(uint32_t buf[4], uint32_t const in[16]);
 
 /*
  * This is needed to make RSAREF happy on some MS-DOS compilers.
index 6d3302f0d4565d3dc002d1ebb8db708a95bac870..356bbc91c8e1661bb0626c370958ddcf15aa9ab3 100644 (file)
--- a/options.c
+++ b/options.c
@@ -55,12 +55,20 @@ enum {
     LA_RETRIEVEERROR
 };
 
-/* options still left: CgGhHjJoORTWxXYz */
-static const char *shortoptions = 
+static const char *shortoptions =
+/* options still left: ghHjJoRTWxXYz */
+#ifdef HAVE_LIBPWMD
+       "O:C:G:"
+#endif
        "?Vcsvd:NqL:f:i:p:UP:A:t:E:Q:u:akKFnl:r:S:Z:b:B:e:m:I:M:yw:D:";
 
 static const struct option longoptions[] = {
 /* this can be const because all flag fields are 0 and will never get set */
+#ifdef HAVE_LIBPWMD
+  {"pwmd-socket",      required_argument,  (int *) 0, 'C' },
+  {"pwmd-file",                required_argument,  (int *) 0, 'G' },
+  {"pinentry-timeout", required_argument,  (int *) 0, 'O' },
+#endif
   {"help",     no_argument,       (int *) 0, '?' },
   {"version",  no_argument,       (int *) 0, 'V' },
   {"check",    no_argument,       (int *) 0, 'c' },
@@ -220,6 +228,17 @@ int parsecmdline (int argc /** argument count */,
                            longoptions, &option_index)) != -1)
     {
        switch (c) {
+#ifdef HAVE_LIBPWMD
+       case 'C':
+           ctl->pwmd_socket = prependdir(optarg, currentwd);
+           break;
+       case 'G':
+           ctl->pwmd_file = xstrdup(optarg);
+           break;
+       case 'O':
+           rctl->pinentry_timeout = atoi(optarg);
+           break;
+#endif
        case 'V':
            versioninfo = TRUE;
            break;
@@ -626,6 +645,12 @@ int parsecmdline (int argc /** argument count */,
               "                        specify policy for processing messages with retrieve errors\n"));
 
        P(GT_("  -p, --protocol    specify retrieval protocol (see man page)\n"));
+#ifdef HAVE_LIBPWMD
+        P(GT_("  -C, --pwmd-socket pwmd socket path (~/.pwmd/socket)\n"));
+        P(GT_("  -G, --pwmd-file   filename to use on the pwmd server\n"));
+        P(GT_("  -O, --pinentry-timeout   seconds until pinentry is canceled\n"));
+#endif
        P(GT_("  -U, --uidl        force the use of UIDLs (pop3 only)\n"));
        P(GT_("      --port        TCP port to connect to (obsolete, use --service)\n"));
        P(GT_("  -P, --service     TCP service to connect to (can be numeric TCP port)\n"));
index 8a1f3fa8b9daf023a2af5b2fd8518721fdc87f9d..7310f6b91f3be6ea8716a9f65b06dd67dc6d86e6 100644 (file)
@@ -104,6 +104,9 @@ continue    { return CONTINUE; }
 markseen       { return MARKSEEN; }
 
 user(name)?    {SETSTATE(NAME); return USERNAME; }
+pwmd_socket    { return PWMD_SOCKET; }
+pwmd_file      { return PWMD_FILE; }
+pinentry_timeout       { return PINENTRY_TIMEOUT; }
 <INITIAL,NAME>pass(word)?      {SETSTATE(NAME); return PASSWORD; }
 folder(s)?     { return FOLDER; }
 smtp(host)?    { return SMTPHOST; }
index c775233045f4824576096436f8460a6e83e64ca6..f20f2ef6775a4a51ebd2f8e18da0d1c239f48fa9 100644 (file)
@@ -57,6 +57,7 @@ extern char * yytext;
 
 %token DEFAULTS POLL SKIP VIA AKA LOCALDOMAINS PROTOCOL
 %token AUTHENTICATE TIMEOUT KPOP SDPS ENVELOPE QVIRTUAL
+%token PINENTRY_TIMEOUT PWMD_SOCKET PWMD_FILE
 %token USERNAME PASSWORD FOLDER SMTPHOST FETCHDOMAINS MDA BSMTP LMTP
 %token SMTPADDRESS SMTPNAME SPAMRESPONSE PRECONNECT POSTCONNECT LIMIT WARNINGS
 %token INTERFACE MONITOR PLUGIN PLUGOUT
@@ -111,6 +112,13 @@ statement  : SET LOGFILE optmap STRING     {run.logfile = prependdir ($4, rcfiledir);
                | SET NO INVISIBLE              {run.invisible = FALSE;}
                | SET SHOWDOTS                  {run.showdots = FLAG_TRUE;}
                | SET NO SHOWDOTS               {run.showdots = FLAG_FALSE;}
+               | SET PINENTRY_TIMEOUT optmap NUMBER {
+#ifdef HAVE_LIBPWMD
+                   run.pinentry_timeout = $4;
+#else
+                   yyerror(GT_("pwmd not enabled"));
+#endif
+                   }
 
 /* 
  * The way the next two productions are written depends on the fact that
@@ -370,6 +378,22 @@ user_option        : TO mapping_list HERE
                | EXPUNGE NUMBER        {current.expunge     = NUM_VALUE_IN($2);}
 
                | PROPERTIES STRING     {current.properties  = $2;}
+
+               | PWMD_SOCKET STRING    {
+#ifdef HAVE_LIBPWMD
+                   current.pwmd_socket = xstrdup($2);
+#else
+                   yyerror(GT_("pwmd not enabled"));
+#endif
+                                       }
+
+               | PWMD_FILE STRING      {
+#ifdef HAVE_LIBPWMD
+                   current.pwmd_file = xstrdup($2);
+#else
+                   yyerror(GT_("pwmd not enabled"));
+#endif
+                                       }
                ;
 %%