--- postfix-2.0.16-20030921/README_FILES/PAM_README.pam 2003-10-06 23:34:57.000000000 +0200 +++ postfix-2.0.16-20030921/README_FILES/PAM_README 2003-10-06 23:34:57.000000000 +0200 @@ -0,0 +1,26 @@ +PAM map type for Postfix. + +Written by Andrew I Baznikin <dikiyobraz@mail.ru>, JSC ISP "Tel", Russia. + +In order to build postfix with PAM map support, you will need to add +-DHAS_PAM and the libpam library to AUXLIBS, for example: + +make -f Makefile.init makefiles \ + 'CCARGS=-DHAS_PAM' \ + 'AUXLIBS=-L/usr/lib -lpam' + +then, just run 'make'. + +Once postfix is built with PAM map support, you can specify a map type +in main.cf like this: + +local_recipient_maps = pam:smtpcheck + +In this example 'smtpcheck' is service name, applicant is e-mail address of recipient. +Facility is always "auth". See pam(8) for details. + +Add some lines to /etc/pam.conf (or /etc/pam.d/<servicename>) : + #smtpcheck auth sufficient pam_permit.so debug try_first_pass + #smtpcheck auth sufficient pam_deny.so debug try_first_pass + smtpcheck auth sufficient pam_unix.so debug try_first_pass + smtpcheck auth required pam_radius.so debug try_first_pass --- postfix-2.0.16-20030921/conf/postfix-files.pam 2003-10-06 23:34:57.000000000 +0200 +++ postfix-2.0.16-20030921/conf/postfix-files 2003-10-06 23:34:57.000000000 +0200 @@ -201,6 +201,7 @@ $readme_directory/MYSQL_README:f:root:-:644 $readme_directory/NFS_README:f:root:-:644 $readme_directory/PACKAGE_README:f:root:-:644 +$readme_directory/PAM_README:f:root:-:644 $readme_directory/PCRE_README:f:root:-:644 $readme_directory/QMQP_README:f:root:-:644 $readme_directory/RELEASE_NOTES:f:root:-:644 --- postfix-2.0.16-20030921/src/util/Makefile.in.pam 2003-10-06 23:34:57.000000000 +0200 +++ postfix-2.0.16-20030921/src/util/Makefile.in 2003-10-06 23:38:49.000000000 +0200 @@ -4,8 +4,8 @@ chroot_uid.c clean_env.c close_on_exec.c concatenate.c ctable.c \ dict.c dict_alloc.c dict_db.c dict_dbm.c dict_debug.c dict_env.c \ dict_cidr.c dict_ht.c dict_ldap.c dict_mysql.c dict_ni.c dict_nis.c \ - dict_nisplus.c dict_open.c dict_pcre.c dict_pgsql.c dict_regexp.c \ - dict_static.c dict_tcp.c dict_unix.c dir_forest.c doze.c \ + dict_nisplus.c dict_open.c dict_pam.c dict_pcre.c dict_pgsql.c \ + dict_regexp.c dict_static.c dict_tcp.c dict_unix.c dir_forest.c doze.c \ duplex_pipe.c environ.c events.c exec_command.c fifo_listen.c \ fifo_trigger.c file_limit.c find_inet.c fsspace.c fullname.c \ get_domainname.c get_hostname.c hex_quote.c host_port.c htable.c \ @@ -33,8 +33,8 @@ chroot_uid.o clean_env.o close_on_exec.o concatenate.o ctable.o \ dict.o dict_alloc.o dict_db.o dict_dbm.o dict_debug.o dict_env.o \ dict_cidr.o dict_ht.o dict_ldap.o dict_mysql.o dict_ni.o dict_nis.o \ - dict_nisplus.o dict_open.o dict_pcre.o dict_pgsql.o dict_regexp.o \ - dict_static.o dict_tcp.o dict_unix.o dir_forest.o doze.o \ + dict_nisplus.o dict_open.o dict_pam.o dict_pcre.o dict_pgsql.o \ + dict_regexp.o dict_static.o dict_tcp.o dict_unix.o dir_forest.o doze.o \ duplex_pipe.o environ.o events.o exec_command.o fifo_listen.o \ fifo_trigger.o file_limit.o find_inet.o fsspace.o fullname.o \ get_domainname.o get_hostname.o hex_quote.o host_port.o htable.o \ @@ -60,7 +60,7 @@ HDRS = argv.h attr.h base64_code.h binhash.h chroot_uid.h clean_env.h \ connect.h ctable.h dict.h dict_db.h dict_dbm.h dict_env.h \ dict_cidr.h dict_ht.h dict_ldap.h dict_mysql.h dict_ni.h dict_nis.h \ - dict_nisplus.h dict_pcre.h dict_pgsql.h dict_regexp.h \ + dict_nisplus.h dict_pam.h dict_pcre.h dict_pgsql.h dict_regexp.h \ dict_static.h dict_tcp.h dict_unix.h dir_forest.h events.h \ exec_command.h find_inet.h fsspace.h fullname.h get_domainname.h \ get_hostname.h hex_quote.h host_port.h htable.h inet_addr_host.h \ @@ -615,6 +615,7 @@ dict_db.o: vstring.h dict_db.o: vbuf.h dict_db.o: stringops.h +dict_open.o: dict_pam.h dict_db.o: iostuff.h dict_db.o: myflock.h dict_db.o: dict.h @@ -704,6 +705,15 @@ dict_open.o: vstring.h dict_open.o: split_at.h dict_open.o: htable.h +dict_pam.o: dict_pam.c +dict_pam.o: sys_defs.h +dict_pam.o: mymalloc.h +dict_pam.o: msg.h +dict_pam.o: dict.h +dict_pam.o: vstream.h +dict_pam.o: vbuf.h +dict_pam.o: argv.h +dict_pam.o: dict_pam.h dict_pcre.o: dict_pcre.c dict_pcre.o: sys_defs.h dict_pcre.o: mymalloc.h --- postfix-2.0.16-20030921/src/util/dict_open.c.pam 2003-10-06 23:34:57.000000000 +0200 +++ postfix-2.0.16-20030921/src/util/dict_open.c 2003-10-06 23:34:57.000000000 +0200 @@ -174,6 +174,7 @@ #include <dict_nisplus.h> #include <dict_ni.h> #include <dict_ldap.h> +#include <dict_pam.h> #include <dict_mysql.h> #include <dict_pgsql.h> #include <dict_pcre.h> @@ -228,6 +229,9 @@ #ifdef HAS_POSIX_REGEXP DICT_TYPE_REGEXP, dict_regexp_open, #endif +#ifdef HAS_PAM + DICT_TYPE_PAM, dict_pam_open, +#endif DICT_TYPE_STATIC, dict_static_open, DICT_TYPE_CIDR, dict_cidr_open, 0, --- postfix-2.0.16-20030921/src/util/dict_pam.c.pam 2003-10-06 23:34:57.000000000 +0200 +++ postfix-2.0.16-20030921/src/util/dict_pam.c 2003-10-06 23:34:57.000000000 +0200 @@ -0,0 +1,148 @@ +/*++ +/* NAME +/* dict_pam 3 +/* SUMMARY +/* dictionary manager interface to PAM +/* SYNOPSIS +/* #include <dict_pam.h> +/* +/* DICT *dict_pam_open(service, dummy, dict_flags) +/* const char *service; +/* int dummy; +/* int dict_flags; +/* DESCRIPTION +/* dict_pam_open() implements a dictionary that returns +/* as lookup result the key value on PAM_SUCCESS +/* and 0 on any other. +/* +/* The \fIdummy\fR argument is ignored. +/* SEE ALSO +/* dict(3) generic dictionary manager +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Andrew I Baznikin +/* dikiyobraz@mail.ru +/* http://d.scn.ru +/*--*/ + +/* System library. */ + +#include "sys_defs.h" + +#ifdef HAS_PAM +#include <unistd.h> +#include <security/pam_appl.h> + +/* Utility library. */ + +#include "mymalloc.h" +#include "msg.h" +#include "vstring.h" +#include "dict.h" +#include "dict_pam.h" + +int converse(int, const struct pam_message **, struct pam_response **, void *); + +typedef struct { + DICT dict; + VSTRING *service; +} DICT_PAM; + +/* answer 'Ok' on any request .) */ +int converse(int n, const struct pam_message **msg, + struct pam_response **resp, void *data) +{ + char buf[PAM_MAX_RESP_SIZE]; + int i; + + data = data; + if (n <= 0 || n > PAM_MAX_NUM_MSG) + return (PAM_CONV_ERR); + if ((*resp = calloc(n, sizeof **resp)) == NULL) + return (PAM_BUF_ERR); + for (i = 0; i < n; ++i) { + resp[i]->resp_retcode = 0; + resp[i]->resp = strdup(msg[i]->msg); + } + + return (PAM_SUCCESS); +} + + +/* dict_pam_lookup - access PAM */ + +static const char *dict_pam_lookup(DICT *dict, const char *name) +{ + DICT_PAM *dp = (DICT_PAM *) dict; + int pam_err; + + static pam_handle_t *pamh; + static struct pam_conv pamc; + + dict_errno = 0; + pamc.conv = &converse; + if ((pam_err = pam_start( vstring_str(dp->service), name, &pamc, &pamh)) + != PAM_SUCCESS) + goto pamerr; + + if (msg_verbose) + msg_info("pam: dict_pam_lookup %s with service '%s'", name, vstring_str(dp->service)); + + /* authenticate the applicant */ + if ((pam_err = pam_authenticate(pamh, 0)) != PAM_SUCCESS) + goto pamerr; + + if (msg_verbose) + msg_info("pam: dict_pam_lookup success"); + return (name); + + pamerr: + if (msg_verbose) + msg_warn("PAM error code %d (%s)", pam_err, pam_strerror(pamh, pam_err)); + +/* if ( pam_err == PAM_SERVICE_ERR || pam_err == PAM_AUTHINFO_UNAVAIL ) { */ + if ( pam_err != PAM_PERM_DENIED && pam_err != PAM_AUTH_ERR) { + msg_error("PAM service failure! Possibly, need admin intervention"); + dict_errno = DICT_ERR_RETRY; + } + pam_end(pamh, pam_err); + return (0); +} + +/* dict_pam_close - close PAM dictionary */ + +static void dict_pam_close(DICT *dict) +{ + DICT_PAM *dp = (DICT_PAM *) dict; + + if (msg_verbose) + msg_info("pam: dict_pam_close"); + vstring_free(dp->service); + dict_free(dict); +} + +/* dict_pam_open - make association with PAM */ + +DICT *dict_pam_open(const char *service, int param, int dict_flags) +{ + DICT_PAM *dp; + VSTRING *s, *f; + + if (msg_verbose) + msg_info("pam: dict_pam_open: service %s, param %d, dict_flags %d ", service, param, dict_flags); + + dp = (DICT_PAM *) dict_alloc(DICT_TYPE_PAM, service, sizeof(DICT_PAM)); + + dp->service = vstring_alloc(10); + + vstring_strcpy(dp->service, service); + dp->dict.lookup = dict_pam_lookup; + dp->dict.close = dict_pam_close; + dp->dict.flags = dict_flags | DICT_FLAG_FIXED; + + return (DICT_DEBUG (&dp->dict)); +} +#endif --- postfix-2.0.16-20030921/src/util/dict_pam.h.pam 2003-10-06 23:34:57.000000000 +0200 +++ postfix-2.0.16-20030921/src/util/dict_pam.h 2003-10-06 23:34:57.000000000 +0200 @@ -0,0 +1,36 @@ +#ifndef _DICT_PAM_H_INCLUDED_ +#define _DICT_PAM_H_INCLUDED_ + +/*++ +/* NAME +/* dict_pam 3h +/* SUMMARY +/* dictionary manager interface to PAM +/* SYNOPSIS +/* #include <dict_pam.h> +/* DESCRIPTION +/* .nf + + /* + * Utility library. + */ +#include <dict.h> + + /* + * External interface. + */ +#define DICT_TYPE_PAM "pam" + +extern DICT *dict_pam_open(const char *, int, int); + +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Andrew I Baznikin +/* dikiyobraz@mail.ru +/* http://d.scn.ru +/*--*/ + +#endif