diff -ruN exim-4.68.orig/doc/README.PWMD exim-4.68/doc/README.PWMD --- exim-4.68.orig/doc/README.PWMD 1969-12-31 19:00:00.000000000 -0500 +++ exim-4.68/doc/README.PWMD 2007-10-18 19:31:52.000000000 -0400 @@ -0,0 +1,28 @@ +Password Manager Daemon (pwmd) is a server that listens on a local socket. +Clients connect and send commands that manipulate data that is stored in an +encrypted XML file. + +When LOOKUP_PWMD is enabled at compile time a new lookup command "pwm" is +added along with a new global configuration parameter "pwmd_options". The PWMD +lookup command returns the content of the specified element path. libpwmd +version 5.0.0 or later is required. + +Both the socket to connect to and the data file to open are specified in +"pwmd_options" are separated by a colon character by default. The socket is +optional and defaults to ~/.pwmd/socket if not specified, but the data file is +required. The data filename is the filename only and not a full path. Read +pwmd(1) for more information about the data_directory configuration parameter. + +See the pwmd(1) manual page for password options. It is possible to use +pinentry(1) to retrieve the password when ~/.pwmd/pinentry.conf is setup +correctly (the home directory is of the user who invoked pwmd). + +Example: + + pwmd_options = /path/to/socket:isp + client_name = ${lookup pwmd{$host\tusername}} + client_secret = ${lookup pwmd{$host\tpassword}} + + +Ben Kibbey +http://bjk.sourceforge.net/pwmd/ diff -ruN exim-4.68.orig/scripts/MakeLinks exim-4.68/scripts/MakeLinks --- exim-4.68.orig/scripts/MakeLinks 2007-08-30 10:31:06.000000000 -0400 +++ exim-4.68/scripts/MakeLinks 2007-10-18 17:46:04.000000000 -0400 @@ -83,6 +83,8 @@ ln -s ../../src/lookups/passwd.c passwd.c ln -s ../../src/lookups/pgsql.h pgsql.h ln -s ../../src/lookups/pgsql.c pgsql.c +ln -s ../../src/lookups/pwmd.h pwmd.h +ln -s ../../src/lookups/pwmd.c pwmd.c ln -s ../../src/lookups/spf.h spf.h ln -s ../../src/lookups/spf.c spf.c ln -s ../../src/lookups/sqlite.h sqlite.h diff -ruN exim-4.68.orig/src/config.h.defaults exim-4.68/src/config.h.defaults --- exim-4.68.orig/src/config.h.defaults 2007-08-30 10:31:06.000000000 -0400 +++ exim-4.68/src/config.h.defaults 2007-10-18 17:46:04.000000000 -0400 @@ -84,6 +84,7 @@ #define LOOKUP_ORACLE #define LOOKUP_PASSWD #define LOOKUP_PGSQL +#define LOOKUP_PWMD #define LOOKUP_SQLITE #define LOOKUP_TESTDB #define LOOKUP_WHOSON diff -ruN exim-4.68.orig/src/drtables.c exim-4.68/src/drtables.c --- exim-4.68.orig/src/drtables.c 2007-08-30 10:31:06.000000000 -0400 +++ exim-4.68/src/drtables.c 2007-10-18 17:46:04.000000000 -0400 @@ -89,6 +89,10 @@ #include "lookups/pgsql.h" #endif +#ifdef LOOKUP_PWMD +#include "lookups/pwmd.h" +#endif + #ifdef EXPERIMENTAL_SPF #include "lookups/spf.h" #endif @@ -445,6 +449,22 @@ #endif }, +/* PWMD lookup */ + { + US"pwmd", /* lookup name */ + lookup_querystyle, /* query-style lookup */ +#ifdef LOOKUP_PWMD + pwm_open, /* open function */ + NULL, /* no check function */ + pwm_find, /* find function */ + NULL, /* no close function */ + pwm_tidy, /* tidy function */ + NULL /* no quoting function */ +#else + NULL, NULL, NULL, NULL, NULL, NULL /* lookup not present */ +#endif + }, + /* SPF lookup */ { diff -ruN exim-4.68.orig/src/EDITME exim-4.68/src/EDITME --- exim-4.68.orig/src/EDITME 2007-08-30 10:31:06.000000000 -0400 +++ exim-4.68/src/EDITME 2007-10-18 17:46:04.000000000 -0400 @@ -275,6 +275,10 @@ # LOOKUP_SQLITE=yes # LOOKUP_WHOSON=yes +# Enable content retrieval of an element path from the Password Manager +# Daemon. Be sure to add "-lpwmd" to LOOKUP_LIBS below. +# LOOKUP_PWMD=yes + # These two settings are obsolete; all three lookups are compiled when # LOOKUP_LSEARCH is enabled. However, we retain these for backward # compatibility. Setting one forces LOOKUP_LSEARCH if it is not set. diff -ruN exim-4.68.orig/src/exim.c exim-4.68/src/exim.c --- exim-4.68.orig/src/exim.c 2007-08-30 10:31:06.000000000 -0400 +++ exim-4.68/src/exim.c 2007-10-18 17:46:04.000000000 -0400 @@ -962,6 +962,9 @@ #ifdef LOOKUP_PGSQL fprintf(f, " pgsql"); #endif +#ifdef LOOKUP_PWMD + fprintf(f, " pwmd"); +#endif #ifdef LOOKUP_SQLITE fprintf(f, " sqlite"); #endif diff -ruN exim-4.68.orig/src/expand.c exim-4.68/src/expand.c --- exim-4.68.orig/src/expand.c 2007-08-30 10:31:06.000000000 -0400 +++ exim-4.68/src/expand.c 2007-10-18 18:40:12.000000000 -0400 @@ -5965,6 +5965,9 @@ #ifdef LOOKUP_PGSQL pgsql_servers = argv[i]; #endif + #ifdef LOOKUP_PWMD + pwmd_options = argv[i]; + #endif } #ifdef EXIM_PERL else opt_perl_startup = argv[i]; diff -ruN exim-4.68.orig/src/globals.c exim-4.68/src/globals.c --- exim-4.68.orig/src/globals.c 2007-08-30 10:31:06.000000000 -0400 +++ exim-4.68/src/globals.c 2007-10-18 18:39:49.000000000 -0400 @@ -83,6 +83,10 @@ uschar *mysql_servers = NULL; #endif +#ifdef LOOKUP_PWMD +uschar *pwmd_options = NULL; +#endif + #ifdef LOOKUP_ORACLE uschar *oracle_servers = NULL; #endif diff -ruN exim-4.68.orig/src/globals.h exim-4.68/src/globals.h --- exim-4.68.orig/src/globals.h 2007-08-30 10:31:06.000000000 -0400 +++ exim-4.68/src/globals.h 2007-10-18 18:39:57.000000000 -0400 @@ -43,6 +43,10 @@ extern uschar *mysql_servers; /* List of servers and connect info */ #endif +#ifdef LOOKUP_PWMD +extern uschar *pwmd_options; /* Socket and data filename. */ +#endif + #ifdef LOOKUP_ORACLE extern uschar *oracle_servers; /* List of servers and connect info */ #endif diff -ruN exim-4.68.orig/src/lookups/Makefile exim-4.68/src/lookups/Makefile --- exim-4.68.orig/src/lookups/Makefile 2007-08-30 10:31:06.000000000 -0400 +++ exim-4.68/src/lookups/Makefile 2007-10-18 17:46:04.000000000 -0400 @@ -6,7 +6,7 @@ # defined, dummy modules get compiled. OBJ = cdb.o dbmdb.o dnsdb.o dsearch.o ibase.o ldap.o lsearch.o mysql.o nis.o \ - nisplus.o oracle.o passwd.o pgsql.o spf.o sqlite.o testdb.o whoson.o \ + nisplus.o oracle.o passwd.o pgsql.o pwmd.o spf.o sqlite.o testdb.o whoson.o \ lf_check_file.o lf_quote.o lf_sqlperform.o lookups.a: $(OBJ) @@ -37,6 +37,7 @@ oracle.o: $(HDRS) oracle.c oracle.h passwd.o: $(HDRS) passwd.c passwd.h pgsql.o: $(HDRS) pgsql.c pgsql.h +pwmd.o: $(HDRS) pwmd.c pwmd.h spf.o: $(HDRS) spf.c spf.h sqlite.o: $(HDRS) sqlite.c sqlite.h testdb.o: $(HDRS) testdb.c testdb.h diff -ruN exim-4.68.orig/src/lookups/pwmd.c exim-4.68/src/lookups/pwmd.c --- exim-4.68.orig/src/lookups/pwmd.c 1969-12-31 19:00:00.000000000 -0500 +++ exim-4.68/src/lookups/pwmd.c 2007-10-18 19:55:45.000000000 -0400 @@ -0,0 +1,158 @@ +/* + Copyright (C) 2007 Ben Kibbey + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#include "../exim.h" + +#ifndef LOOKUP_PWMD +static void dummy(int x) { dummy(x-1); } +#else +#include +#include "pwmd.h" + +struct pwm_connection_s { + char *socket; + char *file; + pwm_t *handle; + struct pwm_connection_s *next; +}; + +static struct pwm_connection_s *pwm_connections = NULL; + +void *pwm_open(uschar *filename, uschar **errmsg) +{ + pwmd_init(); + return (void *)(1); +} + +void pwm_tidy(void) +{ + struct pwm_connection_s *cn; + + for (cn = pwm_connections; cn; cn = cn->next) { + DEBUG(D_lookup) debug_printf("close PWMD connection: socket=%s file=%s\n", cn->socket ? cn->socket : "default socket", cn->file); + pwmd_close(cn->handle); + } +} + +int pwm_find(void *handle, uschar *filename, uschar *query, int length, + uschar **result, uschar **errmsg, BOOL *do_cache) +{ + struct pwm_connection_s *cn; + uschar *socket = NULL; + uschar *file = NULL; + uschar *arg = NULL; + int sep = 0; + uschar buffer[512]; + uschar *options = pwmd_options; + char *cmd_result; + int i = 0; + gpg_error_t error; + + *do_cache = TRUE; + + /* pwmd_options = [>sep] [socket]filename */ + while ((arg = string_nextinlist(&options, &sep, buffer, sizeof(buffer))) != NULL) { + switch (i++) { + case 0: + socket = *arg ? string_copy(arg) : NULL; + break; + case 1: + file = string_copy(arg); + break; + default: + break; + } + } + + if (i < 2) { + *errmsg = string_sprintf("%s: invalid number of arguments to pwmd_options\n", __FUNCTION__); + return FAIL; + } + + for (cn = pwm_connections; cn; cn = cn->next) { + if (!socket && !cn->socket) { + if (Ustrcmp(file, cn->file) == 0) + break; + + continue; + } + + if (Ustrcmp(socket, cn->socket) == 0) { + if (Ustrcmp(file, cn->file) == 0) + break; + } + } + + if (!cn) { + cn = store_get(sizeof(struct pwm_connection_s)); + cn->handle = pwmd_connect(socket, &error); + + if (!cn->handle) { + *errmsg = string_sprintf("pwmd_connect(): %s\n", pwmd_strerror(error)); + *do_cache = FALSE; + return DEFER; + } + + error = pwmd_command(cn->handle, &cmd_result, "OPTION CLIENT NAME=exim"); + + if (error) { + *errmsg = string_sprintf("pwmd_command(OPTION): %s\n", pwmd_strerror(error)); + *do_cache = FALSE; + return DEFER; + } + + DEBUG(D_lookup) debug_printf("open PWMD connection: %s\n", cn->socket ? cn->socket : "default socket"); + cn->socket = socket ? string_copy(socket) : NULL; + cn->file = string_copy(file); + cn->next = pwm_connections; + pwm_connections = cn; + error = pwmd_open(cn->handle, cn->file); + + if (error) { + *errmsg = string_sprintf("pwmd_open(): %s\n", pwmd_strerror(error)); + *do_cache = FALSE; + return DEFER; + } + + DEBUG(D_lookup) debug_printf("open PWMD file: %s\n", cn->file); + } + +again: + error = pwmd_command(cn->handle, &cmd_result, "GET %s\n", query); + + if (error) { + if (error == EPWMD_FILE_MODIFIED) { + do { + error = pwmd_open(cn->handle, cn->file); + } while (error == EPWMD_FILE_MODIFIED); + + if (!error) + goto again; + } + + *errmsg = string_sprintf("pwmd error: GET: %s\n", pwmd_strerror(error)); + *do_cache = FALSE; + return FAIL; + } + + DEBUG(D_lookup) debug_printf("pwmd GET succeeded\n"); + *result = string_copy(cmd_result); + pwmd_free_result(cmd_result); + return OK; +} + +#endif diff -ruN exim-4.68.orig/src/lookups/pwmd.h exim-4.68/src/lookups/pwmd.h --- exim-4.68.orig/src/lookups/pwmd.h 1969-12-31 19:00:00.000000000 -0500 +++ exim-4.68/src/lookups/pwmd.h 2007-10-18 17:46:04.000000000 -0400 @@ -0,0 +1,25 @@ +/* + Copyright (C) 2007 Ben Kibbey + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#ifndef PWMD_H +#define PWMD_H + +extern void *pwm_open(uschar *, uschar **); +extern int pwm_find(void *, uschar *, uschar *, int, uschar **, uschar **, BOOL *); +extern void pwm_tidy(void); + +#endif diff -ruN exim-4.68.orig/src/readconf.c exim-4.68/src/readconf.c --- exim-4.68.orig/src/readconf.c 2007-08-30 10:31:06.000000000 -0400 +++ exim-4.68/src/readconf.c 2007-10-18 18:39:40.000000000 -0400 @@ -297,6 +297,9 @@ { "print_topbitchars", opt_bool, &print_topbitchars }, { "process_log_path", opt_stringptr, &process_log_path }, { "prod_requires_admin", opt_bool, &prod_requires_admin }, +#ifdef LOOKUP_PWMD + { "pwmd_options", opt_stringptr, &pwmd_options }, +#endif { "qualify_domain", opt_stringptr, &qualify_domain_sender }, { "qualify_recipient", opt_stringptr, &qualify_domain_recipient }, { "queue_domains", opt_stringptr, &queue_domains },