diff -ru fetchmail-6.3.8.orig/README.pwmd fetchmail-6.3.8/README.pwmd
--- fetchmail-6.3.8.orig/README.pwmd 1969-12-31 19:00:00.000000000 -0500
+++ fetchmail-6.3.8/README.pwmd 2007-06-23 21:40:04.000000000 -0400
@@ -0,0 +1,33 @@
+When compiled with pwmd (Password Manager Daemon) support (--enable-pwmd),
+fetchmail can retrieve server details from pwmd. Two new configuration
+parameters are added: pwmd_socket, to specify the socket to connect to, and
+pwmd_file (required) which specifies the filename on the server to open.
+
+The data that fetchmail will use is stored in an encrypted XML file and has
+the following structure:
+
+
+ - Optional (--username/username)
+ - Optional (--password/password)
+ - POP3/IMAP/etc.
+ - Required (servername/via)
+ - Required (--service/protocol)
+ - Optional (--ssl/ssl)
+ - Optional (--sslfingerprint/sslfingerprint)
+
+
+
+A minimal fetchmailrc might look like this:
+
+poll isp proto POP3:
+ pwmd_file default
+
+Or from the command line:
+ fetchmail -f fetchmailrc isp
+ fetchmail --pwmd-file somefile -p POP3 isp
+
+The password to open the encrypted data file is either cached on the server
+(the file has been opened before), or gotten from pinentry(1).
+
+Ben Kibbey
+http://bjk.sourceforge.net/pwmd/.
diff -ru fetchmail-6.3.8.orig/configure.ac fetchmail-6.3.8/configure.ac
--- fetchmail-6.3.8.orig/configure.ac 2007-04-06 14:10:58.000000000 -0400
+++ fetchmail-6.3.8/configure.ac 2007-06-23 21:38:56.000000000 -0400
@@ -256,6 +256,22 @@
AC_MSG_RESULT(root-mode pid file will go in $dir)
AC_DEFINE_UNQUOTED(PID_DIR, "$dir", 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 >= 2.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.
diff -ru fetchmail-6.3.8.orig/fetchmail.c fetchmail-6.3.8/fetchmail.c
--- fetchmail-6.3.8.orig/fetchmail.c 2007-03-30 03:52:16.000000000 -0400
+++ fetchmail-6.3.8/fetchmail.c 2007-06-23 22:12:06.000000000 -0400
@@ -146,6 +146,64 @@
const char *iana_charset;
+#ifdef HAVE_LIBPWMD
+static void exit_with_pwmd_error()
+{
+ gpg_err_code_t code = gpg_err_code(pwmd_error);
+
+ warnx(GT_("pwmd: error %i: %s"), code, pwmd_strerror(pwmd_error));
+ exit(PS_UNDEFINED);
+}
+
+static void pwmd_set_agent_strings(const char *filename)
+{
+ char buf[255];
+
+ /*
+ * Use pinentry for password retrieval. Since version 0.3 of pwmd
+ * there is an option to push files into the file cache when the
+ * server starts up. For a daemonized fetchmail, this may be
+ * required because there won't be a way to get the key without a
+ * tty that pinentry requires.
+ */
+ if (pwmd_setopt(pwm, &pwmd_error, PWMD_OPTION_PINENTRY, 1) != PWMD_OK)
+ exit_with_pwmd_error();
+
+ /*
+ * Set the text to be used in the pinentry dialog.
+ */
+ if (pwmd_setopt(pwm, &pwmd_error, PWMD_OPTION_TITLE,
+ "Password Manager Daemon: Fetchmail") != PWMD_OK)
+ exit_with_pwmd_error();
+
+ snprintf(buf, sizeof(buf),
+ "A password is needed to open the file \"%s\". Please\n"
+ "enter the password below.", filename);
+
+ if (pwmd_setopt(pwm, &pwmd_error, PWMD_OPTION_DESC, buf) != PWMD_OK)
+ exit_with_pwmd_error();
+}
+
+static void pwmd_do_connect(const char *socketname, const char *filename)
+{
+ /*
+ * Try and connect to pwmd.
+ */
+ if ((pwm = pwmd_connect(socketname, &pwmd_error)) == NULL)
+ exit_with_pwmd_error();
+
+ pwmd_set_agent_strings(filename);
+
+ /*
+ * Try and open the file so we can later get account/server credentials. If
+ * the file is not cached on the server, pinentry(1) will ask for the
+ * password.
+ */
+ if (pwmd_open(pwm, &pwmd_error, filename) != PWMD_OK)
+ exit_with_pwmd_error();
+}
+#endif
+
int main(int argc, char **argv)
{
int bkgd = FALSE;
@@ -276,6 +334,9 @@
#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);
@@ -988,6 +1049,146 @@
#undef FLAG_MERGE
}
+#ifdef HAVE_LIBPWMD
+static char *protocol_to_service(int protocol)
+{
+ switch (protocol) {
+#ifdef POP2_ENABLE
+ case P_POP2:
+ return "POP2";
+#endif
+#ifdef POP3_ENABLE
+ case P_POP3:
+ return "POP3";
+#endif
+#ifdef IMAP_ENABLE
+ case P_IMAP:
+ return "IMAP";
+#endif
+ case P_APOP:
+ return "APOP";
+ case P_RPOP:
+ return "RPOP";
+ case P_ETRN:
+ return "ETRN";
+ case P_ODMR:
+ return "ODMR";
+ default:
+ return NULL;
+ }
+
+ return NULL;
+}
+
+static int pwmd_get_details(const char *pwmd_account, int protocol,
+ struct query *ctl)
+{
+ char *prot = protocol_to_service(protocol);
+ char *p;
+
+ /*
+ * Get the hostname for this protocol. Element path must be
+ * account->[protocol]->hostname.
+ */
+ if (pwmd_command(pwm, &pwmd_result, &pwmd_error, "GET %s\t%s\thostname", pwmd_account, prot) != PWMD_OK) {
+ if (gpg_err_code(pwmd_error) == EPWMD_ELEMENT_NOT_FOUND) {
+ warnx(GT_("%s->%s->hostname: %s"), pwmd_account, prot, pwmd_strerror(pwmd_error));
+ exit(PS_SYNTAX);
+ }
+ else
+ exit_with_pwmd_error();
+ }
+
+ ctl->server.pollname = xstrdup(pwmd_account);
+ ctl->server.via = xstrdup(pwmd_result);
+ pwmd_free_result(pwmd_result);
+
+ /*
+ * Server port. Element path must be account->[protocol]->port. Should be
+ * required because the element path wouldn't exist with out it. But
+ * maybe not because fetchmail trys standard ports if not specified. This
+ * may be a security risk. Might be better to have 'ssl' required.
+ */
+ if (pwmd_command(pwm, &pwmd_result, &pwmd_error, "GET %s\t%s\tport", pwmd_account, prot) != PWMD_OK) {
+ if (gpg_err_code(pwmd_error) == EPWMD_ELEMENT_NOT_FOUND) {
+ warnx(GT_("%s->%s->port: %s"), pwmd_account, prot, pwmd_strerror(pwmd_error));
+ exit(PS_SYNTAX);
+ }
+ else
+ exit_with_pwmd_error();
+ }
+
+ p = xstrdup(pwmd_result);
+ ctl->server.service = p;
+ pwmd_free_result(pwmd_result);
+
+ /*
+ * Get the remote username. Element must be account->username.
+ */
+ if (pwmd_command(pwm, &pwmd_result, &pwmd_error, "GET %s\tusername", pwmd_account) != PWMD_OK) {
+ if (gpg_err_code(pwmd_error) == EPWMD_ELEMENT_NOT_FOUND)
+ warnx(GT_("%s->username: %s"), pwmd_account, pwmd_strerror(pwmd_error));
+ else
+ exit_with_pwmd_error();
+ }
+ else {
+ ctl->remotename = xstrdup(pwmd_result);
+ ctl->server.esmtp_name = xstrdup(ctl->remotename);
+ pwmd_free_result(pwmd_result);
+ }
+
+ /*
+ * Get the remote password. Element must be account->password.
+ */
+ if (pwmd_command(pwm, &pwmd_result, &pwmd_error, "GET %s\tpassword", pwmd_account) != PWMD_OK)
+ if (gpg_err_code(pwmd_error) == EPWMD_ELEMENT_NOT_FOUND)
+ warnx(GT_("%s->password: %s"), pwmd_account, pwmd_strerror(pwmd_error));
+ else
+ exit_with_pwmd_error();
+ else {
+ ctl->password= xstrdup(pwmd_result);
+ pwmd_free_result(pwmd_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.
+ */
+ if (pwmd_command(pwm, &pwmd_result, &pwmd_error, "GET %s\t%s\tssl", pwmd_account, prot) != PWMD_OK) {
+ if (gpg_err_code(pwmd_error) == EPWMD_ELEMENT_NOT_FOUND)
+ warnx(GT_("%s->%s->ssl: %s"), pwmd_account, prot, pwmd_strerror(pwmd_error));
+ else
+ exit_with_pwmd_error();
+ }
+ else {
+ p = xstrdup(pwmd_result);
+ ctl->use_ssl = atoi(p);
+ ctl->use_ssl = (ctl->use_ssl >= 1) ? FLAG_TRUE : FLAG_FALSE;
+ pwmd_free_result(pwmd_result);
+ free(p);
+ }
+
+ /*
+ * account->[protocol]->sslfingerprint.
+ */
+ if (pwmd_command(pwm, &pwmd_result, &pwmd_error, "GET %s\t%s\tsslfingerprint", pwmd_account, prot) != PWMD_OK) {
+ if (gpg_err_code(pwmd_error) == EPWMD_ELEMENT_NOT_FOUND)
+ warnx(GT_("%s->%s->sslfingerprint: %s"), pwmd_account, prot, pwmd_strerror(pwmd_error));
+ else
+ exit_with_pwmd_error();
+ }
+ else {
+ p = xstrdup(pwmd_result);
+ ctl->sslfingerprint = p;
+ pwmd_free_result(pwmd_result);
+ }
+#endif
+
+ return 0;
+}
+#endif
+
/** Load configuration files.
* \return - true if no servers found on the command line
* - false if servers found on the command line */
@@ -1045,8 +1246,30 @@
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) {
+ warnx(GT_("fetchmail: %s configuration invalid, pwmd_file requires a protocol specification"),
+ ctl->server.pollname);
+ exit(PS_SYNTAX);
+ }
+
+ pwmd_do_connect(ctl->pwmd_socket, ctl->pwmd_file);
+ pwmd_get_details(ctl->server.pollname,
+ ctl->server.protocol, ctl);
+ pwmd_close(pwm);
+ }
+ }
+#else
for (ctl = querylist; ctl; ctl = ctl->next)
ctl->active = !ctl->server.skip;
+#endif
}
else
for (; optind < argc; optind++)
@@ -1067,6 +1290,24 @@
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) {
+ warnx(GT_("%s configuration invalid, pwmd_file requires a protocol specification"),
+ ctl->server.pollname);
+ exit(PS_SYNTAX);
+ }
+
+ pwmd_do_connect(ctl->pwmd_socket, ctl->pwmd_file);
+ pwmd_get_details(ctl->server.pollname,
+ ctl->server.protocol, ctl);
+ pwmd_close(pwm);
+ }
+#endif
}
if (!predeclared)
@@ -1077,8 +1318,29 @@
* call later on.
*/
ctl = hostalloc((struct query *)NULL);
- ctl->server.via =
- ctl->server.pollname = xstrdup(argv[optind]);
+
+#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) {
+ warnx(GT_("Option --pwmd-file needs a service (-p) parameter."));
+ exit(PS_SYNTAX);
+ }
+
+ pwmd_do_connect(cmd_opts.pwmd_socket, cmd_opts.pwmd_file);
+ pwmd_get_details(argv[optind], cmd_opts.server.protocol,
+ ctl);
+ pwmd_close(pwm);
+ }
+ 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;
}
diff -ru fetchmail-6.3.8.orig/fetchmail.h fetchmail-6.3.8/fetchmail.h
--- fetchmail-6.3.8.orig/fetchmail.h 2007-03-17 21:11:43.000000000 -0400
+++ fetchmail-6.3.8/fetchmail.h 2007-06-23 21:42:42.000000000 -0400
@@ -39,6 +39,10 @@
# include "trio/trio.h"
#endif
+#ifdef HAVE_LIBPWMD
+#include
+#endif
+
/* We need this for strstr */
#if !defined(HAVE_STRSTR) && !defined(strstr)
char *strstr(const char *, const char *);
@@ -313,6 +317,11 @@
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 */
@@ -455,6 +464,11 @@
extern char *sdps_envfrom;
extern char *sdps_envto;
#endif /* SDPS_ENABLE */
+#ifdef HAVE_LIBPWMD
+pwm_t *pwm; /* the handle */
+char *pwmd_result; /* server result */
+gpg_error_t pwmd_error; /* return value from pwmd_command() */
+#endif
extern const char *iana_charset; /* IANA assigned charset name */
diff -ru fetchmail-6.3.8.orig/Makefile.am fetchmail-6.3.8/Makefile.am
--- fetchmail-6.3.8.orig/Makefile.am 2007-04-06 14:09:17.000000000 -0400
+++ fetchmail-6.3.8/Makefile.am 2007-06-23 21:38:56.000000000 -0400
@@ -18,6 +18,11 @@
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)
diff -ru fetchmail-6.3.8.orig/options.c fetchmail-6.3.8/options.c
--- fetchmail-6.3.8.orig/options.c 2006-08-14 19:04:02.000000000 -0400
+++ fetchmail-6.3.8/options.c 2007-06-23 21:38:56.000000000 -0400
@@ -53,12 +53,21 @@
LA_IDLE
};
+#ifdef HAVE_LIBPWMD
+static const char *shortoptions =
+ "C:G:?Vcsvd:NqL:f:i:p:UP:A:t:E:Q:u:akKFnl:r:S:Z:b:B:e:m:I:M:yw:D:";
+#else
/* options still left: CgGhHjJoORTWxXYz */
static const char *shortoptions =
"?Vcsvd:NqL:f:i:p:UP:A:t:E:Q:u:akKFnl:r:S:Z:b:B:e:m:I:M:yw:D:";
+#endif
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' },
+#endif
{"help", no_argument, (int *) 0, '?' },
{"version", no_argument, (int *) 0, 'V' },
{"check", no_argument, (int *) 0, 'c' },
@@ -248,6 +257,14 @@
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;
+#endif
case 'V':
versioninfo = TRUE;
break;
@@ -618,6 +635,11 @@
P(GT_(" --plugout specify external command to open smtp connection\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"));
+#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"));
diff -ru fetchmail-6.3.8.orig/rcfile_l.l fetchmail-6.3.8/rcfile_l.l
--- fetchmail-6.3.8.orig/rcfile_l.l 2006-08-14 19:04:02.000000000 -0400
+++ fetchmail-6.3.8/rcfile_l.l 2007-06-23 21:38:56.000000000 -0400
@@ -114,6 +114,8 @@
user(name)? {SETSTATE(NAME); return USERNAME; }
+pwmd_socket { return PWMD_SOCKET; }
+pwmd_file { return PWMD_FILE; }
pass(word)? {SETSTATE(NAME); return PASSWORD; }
folder(s)? { return FOLDER; }
smtp(host)? { return SMTPHOST; }
diff -ru fetchmail-6.3.8.orig/rcfile_y.y fetchmail-6.3.8/rcfile_y.y
--- fetchmail-6.3.8.orig/rcfile_y.y 2006-12-08 07:09:09.000000000 -0500
+++ fetchmail-6.3.8/rcfile_y.y 2007-06-23 21:38:56.000000000 -0400
@@ -63,7 +63,7 @@
%token DEFAULTS POLL SKIP VIA AKA LOCALDOMAINS PROTOCOL
%token AUTHENTICATE TIMEOUT KPOP SDPS ENVELOPE QVIRTUAL
-%token USERNAME PASSWORD FOLDER SMTPHOST FETCHDOMAINS MDA BSMTP LMTP
+%token PWMD_SOCKET PWMD_FILE USERNAME PASSWORD FOLDER SMTPHOST FETCHDOMAINS MDA BSMTP LMTP
%token SMTPADDRESS SMTPNAME SPAMRESPONSE PRECONNECT POSTCONNECT LIMIT WARNINGS
%token INTERFACE MONITOR PLUGIN PLUGOUT
%token IS HERE THERE TO MAP WILDCARD
@@ -243,6 +243,20 @@
userdef : USERNAME STRING {current.remotename = xstrdup($2);}
| USERNAME mapping_list HERE
| USERNAME STRING THERE {current.remotename = xstrdup($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
+ }
;
user0opts : /* EMPTY */