v. 2023.02.18 Combined patch for vpopmail-5.4.33 by Roberto Puzzanghera More info here: https://notes.sagredo.eu/en/qmail-notes-185/installing-and-configuring-vpopmail-81.html https://notes.sagredo.eu/en/qmail-notes-185/dovecot-vpopmail-auth-driver-removal-migrating-to-the-sql-driver-241.html ================================================================================================== == This patch puts together * A patch to make vpopmail store domain aliases to MySQL. This gets dovecot's sql auth driver aware of domain aliases, provided that you modify the sql query accordingly. More info here https://notes.sagredo.eu/en/qmail-notes-185/dovecot-vpopmail-auth-driver-removal-241.html See doc/README.sql-aliasdomains for more info. https://notes.sagredo.eu/files/qmail/patches/vpopmail/vpopmail-5.4.33_sql-aliasdomains.patch * A patch which installs the sql procedures needed for the dovecot's password_query and user_query for servers with one table for each domains (--disable-many-domains). You have to add --enable-mysql-bin to you configure command. The sql procedures are in the vpopmail-5.4.33/dovecot/ folder and it will be copied to ~/vpopmail/etc/. It supports aliasdomains and user/domain limits. This feature does nothing if you have all domains in the vpopmail table (--enable-many-domains). See doc/README.dovecot-sql-procedures for more info. https://notes.sagredo.eu/files/qmail/patches/vpopmail/vpopmail-5.4.33_dovecot-sql-procedures.patch * A patch which makes vpopmail to copy your favourite delivery agent (stored in QMAILDIR/control/defauldelivery) into the .qmail-default file of any newly created domain, overriding the default vpopmail's behaviour, where vpopmail copies its delivery agent vdelivermail. configure --enable-defaultdelivery (default is OFF) to enable this functionality. See doc/README.defaultdelivery for more info. https://notes.sagredo.eu/files/qmail/patches/vpopmail/vpopmail-5.4.33-defaultdelivery.patch * vusaged-configure patch It seems that at least on Debian 11 vusaged refuses to run the configure successfully, as the mysql libraries are not linked with this error: configure: error: No vauth_getpw in libvpopmail After some inspection, I noticed that avoiding the break of the configure command, the following make command will find libmysqlclient and compile with no problems, and the program works as expected. NB: an "autoreconf -f -i" into the vusaged directory is needed before configuring, as the configure.ac was modified. https://notes.sagredo.eu/files/qmail/patches/vpopmail/vpopmail-5.4.33-vusaged-configure.patch * A "recipient check" program to be used with E. Hoffmann's s/qmail. Look at doc/README.vrcptcheck for more info. https://notes.sagredo.eu/files/qmail/patches/vpopmail/vpopmail-5.4.33_vrcptcheck.patch * A cosmetic "vuserinfo -D" patch which prints a new line between users' infos when typing "vuserinfo -D", to improve legibility. https://notes.sagredo.eu/files/qmail/patches/vpopmail/vuserinfo-D_newline.patch * A patch which gets vpopmail to compile with gcc-10 https://notes.sagredo.eu/files/qmail/patches/vpopmail/vpopmail-5.4.33_gcc-10-compat.patch * A patch by Ali Erturk TURKER to fix the following issues: 1- vdelivermail.c checks spamassassin permissions, instead of maildrop permissions. 2- vopen_smtp_relay() return values corrected, so that open_smtp_relay() can detect and report database connection errors (vmysql.c, voracle.pc, vpgsql.c ) 3- vdel_limits() core-dumps if a database connection is not available beforehand. (vmysql.c, voracle.pc ) More info here: https://notes.sagredo.eu/en/qmail-notes-185/installing-and-configuring-vpopmail-81.html#comment2814 https://notes.sagredo.eu/files/qmail/patches/vpopmail/vpopmail_fixes_20230217_1524.patch === Settings * An autoreconf is needed as I modified the original configure.in and Makefile.am files autoreconf -f -i * Browse the doc/ directory for more info ================================================================================================ diff -ruN ../vpopmail-5.4.33-original/Makefile.am vpopmail-5.4.33/Makefile.am --- ../vpopmail-5.4.33-original/Makefile.am 2011-02-28 18:00:45.000000000 +0100 +++ vpopmail-5.4.33/Makefile.am 2022-08-09 14:04:47.325812976 +0200 @@ -19,6 +19,7 @@ MYSQLCONF=$(DESTDIR)@vpopmaildir@/etc/vpopmail.mysql VLIMITS=$(DESTDIR)@vpopmaildir@/etc/vlimits.default VUSAGECCONF=$(DESTDIR)@vpopmaildir@/etc/vusagec.conf +DOVECOT_SQL=$(DESTDIR)@vpopmaildir@/etc/disable-many-domains_procedures.sql noinst_LIBRARIES=libvpopmail.a @@ -31,7 +32,7 @@ vdeldomain vpasswd vadduser vdeluser vaddaliasdomain vsetuserquota \ vpopbull vdeloldusers vmoduser valias vuserinfo vmkpasswd vipmap \ vdominfo vconvert vkill vmoddomlimits vchangepw dotqmail2valias \ - vpopmaild vlist authvchkpw vusagec + vpopmaild vlist authvchkpw vusagec vsavealiasdomains vrcptcheck vusagec_SOURCES = vusagec.c client.c conf.c ippp.c vusagec_LDADD = libvpopmail.a @auth_libs@ @@ -114,6 +115,12 @@ vmoddomlimits_SOURCES = vmoddomlimits.c vmoddomlimits_LDADD = libvpopmail.a @auth_libs@ +vsavealiasdomains_SOURCES = vsavealiasdomains.c +vsavealiasdomains_LDADD = libvpopmail.a @auth_libs@ + +vrcptcheck_SOURCES = vrcptcheck.c +vrcptcheck_LDADD = libvpopmail.a @auth_libs@ + DEFS=-I. @auth_inc@ install: install-recursive vusage-msg @@ -149,6 +156,13 @@ echo "-L@vpopmaildir@/lib -lvpopmail @auth_libs@ @LIBS@" > \ $(DESTDIR)@vpopmaildir@/etc/lib_deps + if test @MANY_DOMAINS@ = 0; then \ + if test ! -r $(DOVECOT_SQL); then \ + $(INSTALL) -o root -m 0644 \ + dovecot/disable-many-domains_procedures.sql $(DOVECOT_SQL); \ + fi \ + fi + if test ! -r $(VUSAGECCONF); then \ $(INSTALL) -o @vpopuser@ -m 0644 -g @vpopgroup@ \ vusagec.conf $(VUSAGECCONF); \ diff -ruN ../vpopmail-5.4.33-original/configure.in vpopmail-5.4.33/configure.in --- ../vpopmail-5.4.33-original/configure.in 2011-02-28 18:00:45.000000000 +0100 +++ vpopmail-5.4.33/configure.in 2022-08-09 14:04:47.326812974 +0200 @@ -1454,6 +1454,29 @@ ;; esac + +#---------------------------------------------------------------------- + +AC_MSG_CHECKING(whether defaultdelivery is enabled) +AC_ARG_ENABLE(defaultdelivery, + [ --enable-defaultdelivery Copy the content of control/defaultdelivery to .qmail-default on domain creation.], + DEFAULT_DELIVERY=$enableval, + [ + DEFAULT_DELIVERY=n + ] +) + +case $DEFAULT_DELIVERY in + 1*|y*|Y*) + AC_MSG_RESULT(yes) + DEFAULT_DELIVERY=1 + AC_DEFINE_UNQUOTED(DEFAULT_DELIVERY,$DEFAULT_DELIVERY,"") + ;; + *) + AC_MSG_RESULT(no) + ;; +esac + #---------------------------------------------------------------------- AC_MSG_CHECKING(whether many-domains is enabled) @@ -1484,6 +1507,92 @@ #---------------------------------------------------------------------- +AC_MSG_CHECKING(whether sql-aliasdomains is enabled) +AC_ARG_ENABLE(sql-aliasdomains, + [ --enable-sql-aliasdomains Saves the domain aliases to database. Only valid for MySQL auth module.], + SQL_ALIASDOMAINS=$enableval, + [ + if [[ "$AUTH_MODULE" != "mysql" ]]; + then + SQL_ALIASDOMAINS=n + else + SQL_ALIASDOMAINS=y + AC_DEFINE_UNQUOTED(SQL_ALIASDOMAINS,$SQL_ALIASDOMAINS,"") + fi + ] +) + +case $SQL_ALIASDOMAINS in + 1*|y*|Y*) + AC_MSG_RESULT(yes) + if [[ "$AUTH_MODULE" != "mysql" ]]; + then + AC_MSG_ERROR(sql-aliasdomains is only supported in the MySQL authentication module.) + else + SQL_ALIASDOMAINS=1 + AC_DEFINE_UNQUOTED(SQL_ALIASDOMAINS,$SQL_ALIASDOMAINS,"") + fi + ;; + *) + AC_MSG_RESULT(no) + SQL_ALIASDOMAINS=0 + ;; +esac + +#---------------------------------------------------------------------- + +# MySQL binary is needed because we have to create the procedure calling an sql file via command line +# This is only with --disable-many-domains +AC_SUBST(MANY_DOMAINS) + +if test $MANY_DOMAINS = 0 && test $SQL_ALIASDOMAINS = 1 +then + + AC_MSG_CHECKING(whether we can locate the MySQL binary) + # default MySQL binary + mysqlbin="" + for f in /usr/bin/mysql /usr/local/mysql/bin/mysql /usr/local/bin/mysql + do + if test -x $f + then + mysqlbin=$f + fi + done + + # AC_ARG_ENABLE (feature, help-string, [action-if-given], [action-if-not-given]) + AC_ARG_ENABLE(mysql-bin, + [ --enable-mysql-bin=PATH Full path to your MySQL binary. Only with --disable-many-domains.], + binmysql=$enableval, + [ + if test "$mysqlbin" = "" + then + AC_MSG_RESULT(no) + AC_MSG_ERROR([Unable to find your MySQL binary, specify --enable-mysql-bin=PATH.]) + fi + ] + ) + + if test ! $binmysql = "yes" + then + if test ! -x $binmysql + then + AC_MSG_RESULT(no) + AC_MSG_ERROR([Unable to find your MySQL binary, specify --enable-mysql-bin=PATH.]) + else + mysqlbin=$binmysql + fi + fi + + AC_MSG_RESULT(yes) + AC_DEFINE_UNQUOTED(MYSQLBIN,"$mysqlbin","") + +else + AC_DEFINE_UNQUOTED(MYSQLBIN,"","") + +fi + +#---------------------------------------------------------------------- + AC_MSG_CHECKING(whether any discontinued --enable commands have been used) AC_ARG_ENABLE(mysql-logging, [], @@ -1838,6 +1947,16 @@ esac +case $DEFAULT_DELIVERY in + 1*|y*|Y*) + echo " defaultdelivery = ON --enable-defaultdelivery" + ;; + *) + echo " defaultdelivery = OFF --disable-defaultdelivery (default)" + ;; +esac + + if test "$USE_SQL" = 1 then if test "$MANY_DOMAINS" = 1 @@ -1848,6 +1967,16 @@ fi fi +if [[ "$AUTH_MODULE" == "mysql" ]]; +then + if test "$SQL_ALIASDOMAINS" = 1 + then + echo "SQL domain aliases = ON domain aliases saved to MySQL --enable-sql-aliasdomains (default)" + else + echo "SQL domain aliases = OFF domain aliases NOT saved to MySQL --disable-sql-aliasdomains" + fi +fi + case $ENABLE_SPAMASSASSIN in 1*|y*|Y*) echo " spamassassin = ON --enable-spamassassin" diff -ruN ../vpopmail-5.4.33-original/doc/README.defaultdelivery vpopmail-5.4.33/doc/README.defaultdelivery --- ../vpopmail-5.4.33-original/doc/README.defaultdelivery 1970-01-01 01:00:00.000000000 +0100 +++ vpopmail-5.4.33/doc/README.defaultdelivery 2022-08-09 14:04:47.327812972 +0200 @@ -0,0 +1,19 @@ +vpopmail-defaultdelivery patch for vpopmail-5.4.33 by Roberto Puzzanghera +More info here https://notes.sagredo.eu/en/qmail-notes-185/installing-and-configuring-vpopmail-81.html + +================================================================================================================== + +Normally vpopmail copies its delivery agent vdelivermail into the .qmail-default file of newly created domains. +This patch makes vpopmail to copy your favourite delivery agent, stored in QMAILDIR/control/defauldelivery. + +== Settings + +An autoreconf is needed as I modified the original configure.in and Makefile.am files. + +Configure as follows: + +autoreconf -f -i +./configure --enable-defaultdelivery (default OFF) + +If the functionality is disabled (--disable-defaultdelivery, which is the default option) vdelivermail is +installed with the "delete" option instead of "bounce-no-mailbox", which is not reasonable anymore. diff -ruN ../vpopmail-5.4.33-original/doc/README.dovecot-sql-procedures vpopmail-5.4.33/doc/README.dovecot-sql-procedures --- ../vpopmail-5.4.33-original/doc/README.dovecot-sql-procedures 1970-01-01 01:00:00.000000000 +0100 +++ vpopmail-5.4.33/doc/README.dovecot-sql-procedures 2022-08-09 14:20:25.167679183 +0200 @@ -0,0 +1,53 @@ +v. 2022.08.09 +vpopmail-dovecot-sql-procedures patch for vpopmail-5.4.33 by Roberto Puzzanghera +More info here https://notes.sagredo.eu/en/qmail-notes-185/installing-and-configuring-vpopmail-81.html + +================================================================================================================== + +If you want to use the dovecot's sql auth driver with one table for each domain (--disable-many-domains) you have +to heavily customize your password_query and user_query. +With this patch vpopmail installs the sql procedures and functions in the database when you create a new domain. +The procedures can be called by dovecot to perform the auth. +The sql stuff supports aliasdomains and mysql limits and will be loaded from ~/vpopmail/etc/disable-many-domains_procedures.sql. +You can customize the sql procedure editing this file. +Be aware that the aliasdomains support requires that you patched your vpopmail accordingly with my +sql-aliasdomains patch. + +Read the reference above for more info. + +================================================================================================================= + +== Settings + +This patch must be installed over the "sql-aliasdomains" patch. + +An autoreconf is needed as I modified the original configure.in and Makefile.am files. + +Configure as follows: + +autoreconf -f -i +./configure --disable-many-domains --enable-sql-aliasdomains --enable-mysql-bin=PATH + +=== dovecot configuration + +auth-sql.conf.ext + +passdb { + driver = sql + args = /usr/local/dovecot/etc/dovecot/dovecot-sql.conf.ext +} + +userdb { + driver = prefetch +} + +# This is for LDA. +userdb { + driver = sql + args = /usr/local/dovecot/etc/dovecot/dovecot-sql.conf.ext +} + +dovecot-sql.conf.ext + +password_query = CALL dovecot_password_query_disable_many_domains('%n','%d','127.0.0.1','%r','%a') +user_query = CALL dovecot_user_query_disable_many_domains('%n','%d') diff -ruN ../vpopmail-5.4.33-original/doc/README.sql-aliasdomains vpopmail-5.4.33/doc/README.sql-aliasdomains --- ../vpopmail-5.4.33-original/doc/README.sql-aliasdomains 1970-01-01 01:00:00.000000000 +0100 +++ vpopmail-5.4.33/doc/README.sql-aliasdomains 2022-08-09 14:04:47.327812972 +0200 @@ -0,0 +1,61 @@ +sql-aliasdomains patch for vpopmail-5.4.33 by Roberto Puzzanghera +More info here https://notes.sagredo.eu/en/qmail-notes-185/dovecot-vpopmail-auth-driver-removal-241.html + +================================================================================================================== + +* A patch to make vpopmail store domain aliases to MySQL. This gets dovecot's sql auth driver + aware of domain aliases, provided that you modify the sql query accordingly. + More info here https://notes.sagredo.eu/en/qmail-notes-185/dovecot-vpopmail-auth-driver-removal-241.html + +* A patch which gets vpopmail to compile with gcc-10 + +== Settings + +* An autoreconf is needed as I modified the original configure.in and Makefile.am files + + autoreconf -f -i + ./configure \ + --enable-auth-module=mysql \ + --enable-sql-aliasdomains (default) + +* Adjust your dovecot-sql.conf.ext in order to auth both real and alias domains: + (more info here https://notes.sagredo.eu/en/qmail-notes-185/installing-dovecot-and-sieve-on-a-vpopmail-qmail-server-28.html#sql) + +password_query = \ + SELECT \ + CONCAT(vpopmail.pw_name, '@', vpopmail.pw_domain) AS user, \ + vpopmail.pw_passwd AS password, \ + vpopmail.pw_dir AS userdb_home, \ + 89 AS userdb_uid, \ + 89 AS userdb_gid, \ + CONCAT('*:bytes=', REPLACE(SUBSTRING_INDEX(vpopmail.pw_shell, 'S', 1), 'NOQUOTA', '0')) AS userdb_quota_rule \ + FROM `vpopmail` \ + LEFT JOIN aliasdomains ON aliasdomains.alias='%d' \ + WHERE \ + vpopmail.pw_name='%n' \ + AND \ + (vpopmail.pw_domain='%d' OR vpopmail.pw_domain=aliasdomains.domain) \ + AND \ + ('%a'!='995' OR !(vpopmail.pw_gid & 2)) \ + AND \ + ('%r'!='[WEBMAIL-IP]' OR !(vpopmail.pw_gid & 4)) \ + AND \ + ('%r'='WEBMAIL-IP' OR '%a'!='993' OR !(vpopmail.pw_gid & 8)) + +user_query = \ + SELECT \ + vpopmail.pw_dir AS home, \ + 89 AS uid, \ + 89 AS gid \ + FROM vpopmail \ + WHERE \ + vpopmail.pw_name='%n' \ + AND \ + vpopmail.pw_domain='%d' + +* Create/delete aliasdomains in the usual way with vaddaliasdomain/vdeldomain + +* If you already have aliasdomains, you have to populate the dbtable. You can use my "vsavealiasdomains" program + to save all your domain aliases to MySQL. + Type "vsavealiasadomains -A" to save all your domain aliases to MySQL. + Type "vsavealiasadomains -h" for more options. diff -ruN ../vpopmail-5.4.33-original/doc/README.vrcptcheck vpopmail-5.4.33/doc/README.vrcptcheck --- ../vpopmail-5.4.33-original/doc/README.vrcptcheck 1970-01-01 01:00:00.000000000 +0100 +++ vpopmail-5.4.33/doc/README.vrcptcheck 2022-08-09 14:04:47.327812972 +0200 @@ -0,0 +1,8 @@ +vrcptcheck is a recipient check for s/qmail + +Just call this program within /var/qmail/control/recipients as follows: + +cat /home/vpopmail/bin/vrcptcheck > /var/qmail/control/recipients + +You have to provide an "autoreconf -f -i" before configuring, as the original +Makefiele.am has been modified. diff -ruN ../vpopmail-5.4.33-original/dovecot/disable-many-domains_procedures.sql vpopmail-5.4.33/dovecot/disable-many-domains_procedures.sql --- ../vpopmail-5.4.33-original/dovecot/disable-many-domains_procedures.sql 1970-01-01 01:00:00.000000000 +0100 +++ vpopmail-5.4.33/dovecot/disable-many-domains_procedures.sql 2022-08-10 12:30:39.894515798 +0200 @@ -0,0 +1,166 @@ +/******************************************************************************************************* + password_query and user_query procedures for dovecot's sql auth in case of --disable-many-domains. + It supports aliasdomains and mysql-limits. + + More info here + https://notes.sagredo.eu/en/qmail-notes-185/dovecot-vpopmail-auth-driver-removal-migrating-to-the-sql-driver-241.html + + By Roberto Puzzanghera + +###### auth-sql.conf.ext + +passdb { + driver = sql + args = /usr/local/dovecot/etc/dovecot/dovecot-sql.conf.ext +} + +userdb { + driver = prefetch +} + +# This is for LDA. +userdb { + driver = sql + args = /usr/local/dovecot/etc/dovecot/dovecot-sql.conf.ext +} + +##### dovecot-sql.conf.ext + +password_query = CALL dovecot_password_query_disable_many_domains('%n','%d','127.0.0.1','%r','%a') +user_query = CALL dovecot_user_query_disable_many_domains('%n','%d') + + ***************************************************************************************************/ + + +/**************************************************************** + Returns the domain table + ****************************************************************/ +DROP FUNCTION IF EXISTS `get_domain_table`; + +DELIMITER $$ +CREATE FUNCTION `get_domain_table`(`d` VARCHAR(100)) RETURNS varchar(100) CHARSET latin1 +BEGIN + + DECLARE domain_table varchar(100); + SET domain_table = dot2underscore(get_real_domain(d)); + + RETURN domain_table; + +END$$ +DELIMITER ; + + +/**************************************************************** + Replaces dots and "-" with undescores in domain name + ****************************************************************/ +DROP FUNCTION IF EXISTS `dot2underscore`; + +DELIMITER $$ +CREATE FUNCTION `dot2underscore`(`d` VARCHAR(100)) RETURNS varchar(100) CHARSET latin1 +BEGIN + + RETURN REPLACE(REPLACE(d, ".", "_"), "-", "_"); + +END$$ +DELIMITER ; + + +/******************************************************************* + Returns the real domain given an alias domain or the domain name + if it's not an alias. + *******************************************************************/ +DROP FUNCTION IF EXISTS `get_real_domain`; + +DELIMITER $$ +CREATE FUNCTION `get_real_domain`(`d` VARCHAR(100)) RETURNS varchar(100) CHARSET latin1 +BEGIN + DECLARE real_domain varchar(100); + + IF NOT + (SELECT 1 FROM INFORMATION_SCHEMA.TABLES + WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME=dot2underscore(d)) + IS NULL THEN + SET real_domain = d; + + ELSEIF NOT + (SELECT 1 FROM aliasdomains WHERE alias=d) + IS NULL THEN + SELECT domain INTO real_domain FROM aliasdomains WHERE alias=d; + + ELSE + SET real_domain = NULL; + + END IF; + + RETURN real_domain; + +END$$ +DELIMITER ; + + +/************************************************************************** + Stored procedure for password_query in case of "disabled many domains" + **************************************************************************/ +DROP PROCEDURE IF EXISTS `dovecot_password_query_disable_many_domains`; + +DELIMITER $$ +CREATE PROCEDURE `dovecot_password_query_disable_many_domains`(IN `name` VARCHAR(255), IN `domain` VARCHAR(255), IN `webmail_ip` VARCHAR(255), IN `remote_ip` VARCHAR(255), IN `port` INT) +BEGIN +DECLARE vpopmail varchar(256); +SET vpopmail = get_domain_table(domain); + +IF (vpopmail) IS NULL THEN + SET @SQL = "SELECT NULL"; +ELSE + SET @SQL = CONCAT("SELECT CONCAT(",vpopmail,".pw_name, '@', '",domain,"') AS user,", + vpopmail,".pw_passwd AS password,", + vpopmail,".pw_dir AS userdb_home, + 89 AS userdb_uid, + 89 AS userdb_gid, + CONCAT('*:bytes=', REPLACE(SUBSTRING_INDEX(",vpopmail,".pw_shell, 'S', 1), 'NOQUOTA', '0')) AS userdb_quota_rule + FROM ",vpopmail," + LEFT JOIN limits ON limits.domain='",get_real_domain(domain),"' + WHERE ",vpopmail,".pw_name='",name,"' + AND + ('",port,"'!='995' OR !(",vpopmail,".pw_gid & 2)) + AND + ('",remote_ip,"'!='",webmail_ip,"' OR !(",vpopmail,".pw_gid & 4)) + AND + ('",remote_ip,"'='",webmail_ip,"' OR '",port,"'!='993' OR !(",vpopmail,".pw_gid & 8)) + AND + ('",remote_ip,"'!='",webmail_ip,"' OR COALESCE(disable_webmail,0)!=1) + AND + ('",remote_ip,"'='",webmail_ip,"' OR COALESCE(disable_imap,0)!=1)"); +END IF; + +PREPARE sql_code FROM @SQL; +EXECUTE sql_code; +DEALLOCATE PREPARE sql_code; + +END$$ +DELIMITER ; + + +/************************************************************************** + Stored procedure for user_query in case of "disabled many domains" + **************************************************************************/ +DROP PROCEDURE IF EXISTS `dovecot_user_query_disable_many_domains`; + +DELIMITER $$ +CREATE PROCEDURE `dovecot_user_query_disable_many_domains`(IN `name` VARCHAR(255), IN `domain` VARCHAR(255)) +BEGIN +DECLARE vpopmail varchar(256); +SET vpopmail = get_domain_table(domain); + +IF (vpopmail) IS NULL THEN + SET @SQL = "SELECT NULL"; +ELSE + set @SQL = concat("SELECT ",vpopmail,".pw_dir AS home, 89 AS uid, 89 AS gid FROM ",vpopmail," where ",vpopmail,".pw_name='",name,"'"); +END IF; + +PREPARE sql_code FROM @SQL; +EXECUTE sql_code; +DEALLOCATE PREPARE sql_code; + +END$$ +DELIMITER ; diff -ruN ../vpopmail-5.4.33-original/vdelivermail.c vpopmail-5.4.33/vdelivermail.c --- ../vpopmail-5.4.33-original/vdelivermail.c 2011-02-28 18:00:45.000000000 +0100 +++ vpopmail-5.4.33/vdelivermail.c 2023-02-18 16:20:05.039673475 +0100 @@ -636,7 +636,7 @@ read_quota_from_maildir (address, maildirquota, sizeof(maildirquota)); quota = maildirquota; } - + /* if the user has a quota set */ #ifdef MAILDROP vget_limits(TheDomain, &limits); @@ -644,7 +644,8 @@ parse_email(maildir_to_email(address), TheUser, TheDomain, AUTH_SIZE); vpw=vauth_getpw(TheUser, TheDomain); } - if ( vpw!=NULL && (limits.disable_spamassassin==1 || + // if ( vpw!=NULL && (limits.disable_spamassassin==1 || + if ( vpw!=NULL && (limits.disable_maildrop==1 || (vpw->pw_gid & NO_MAILDROP)) ) { #endif if ( strncmp(quota, "NOQUOTA", 2) != 0 ) { diff -ruN ../vpopmail-5.4.33-original/vmysql.c vpopmail-5.4.33/vmysql.c --- ../vpopmail-5.4.33-original/vmysql.c 2011-02-28 18:00:45.000000000 +0100 +++ vpopmail-5.4.33/vmysql.c 2023-02-18 16:12:02.842065684 +0100 @@ -96,6 +96,20 @@ void vcreate_lastauth_table(); #endif +char *MYSQL_READ_SERVER; +int MYSQL_READ_PORT; +char *MYSQL_READ_SOCKET; +char *MYSQL_READ_USER; +char *MYSQL_READ_PASSWD; +char *MYSQL_READ_DATABASE; + +char *MYSQL_UPDATE_SERVER; +int MYSQL_UPDATE_PORT; +char *MYSQL_UPDATE_SOCKET; +char *MYSQL_UPDATE_USER; +char *MYSQL_UPDATE_PASSWD; +int MYSQL_UPDATE_VPORT; +char *MYSQL_UPDATE_DATABASE; /************************************************************************/ /* @@ -356,13 +370,19 @@ int vauth_adddomain( char *domain ) { #ifndef MANY_DOMAINS +#ifdef SQL_ALIASDOMAINS + vcreate_sql_procedures(); +#endif vset_default_domain( domain ); return (vauth_create_table (vauth_munch_domain( domain ), TABLE_LAYOUT, 1)); #else /* if creation fails, don't show an error */ vauth_create_table (MYSQL_DEFAULT_TABLE, TABLE_LAYOUT, 0); - return (0); #endif +#ifdef SQL_ALIASDOMAINS + vcreate_aliasdomains_table(); +#endif + return (0); } @@ -900,7 +920,8 @@ return 0; } - if ( (err=vauth_open_update()) != 0 ) return 0; + // open_smtp_relay() expects "-1" on database errors. "0" means duplicate record. (See vpopmail.c) + if ( (err=vauth_open_update()) != 0 ) return (-1); qnprintf( SqlBufUpdate, SQL_BUF_SIZE, "replace into relay ( ip_addr, timestamp ) values ( '%s', %d )", @@ -1849,6 +1870,12 @@ /************************************************************************/ int vdel_limits(const char *domain) { + int err; + + // CHECKS IF A DATABASE CONNECTION IS AVAILABLE, CONNECTS IF NOT. + // THIS CHECK PREVENTS "CORE-DUMP" OF vqadmin.cgi. + if ( (err=vauth_open_update()) != 0 ) return (err); + qnprintf(SqlBufUpdate, SQL_BUF_SIZE, "DELETE FROM limits WHERE domain = '%s'", domain); if (mysql_query(&mysql_update,SqlBufUpdate)) @@ -1866,3 +1893,82 @@ return(strcmp(crypt(clear_pass,vpw->pw_passwd),vpw->pw_passwd)); } + + +/************************************************************************/ +#ifndef MANY_DOMAINS +#ifdef SQL_ALIASDOMAINS +int vcreate_sql_procedures() +{ + char sql_file[256], command[256]; + FILE *sql; + + /* retrieve the file with the sql stuff */ + snprintf(sql_file, sizeof(sql_file), "%s/etc/disable-many-domains_procedures.sql",VPOPMAILDIR); + sql = fopen(sql_file, "r"); + if( sql == NULL ) + { + printf("\nERROR: Missing %s/etc/disable-many-domains_procedures.sql file.\n",VPOPMAILDIR); + exit(EXIT_FAILURE); + } + + /* build the shell command which runs the query */ + snprintf(command, sizeof command, "%s -h %s -P %d -D %s -u %s -p%s < %s", + MYSQLBIN, MYSQL_UPDATE_SERVER, MYSQL_UPDATE_PORT, MYSQL_UPDATE_DATABASE, + MYSQL_UPDATE_USER, MYSQL_UPDATE_PASSWD, sql_file); + system(command); + + fclose(sql); +} +#endif +#endif + +/************************************************************************/ +void vcreate_aliasdomains_table() +{ + /* if creation fails do not throw an error */ + vauth_create_table ("aliasdomains", ALIASDOMAINS_TABLE_LAYOUT, 0); + return; +} + + +/************************************************************************/ +int vcreate_sql_aliasdomain(char *domain, char *alias) +{ + int err; + + if ( (err=vauth_open_update()) != 0 ) return(err); + + qnprintf( SqlBufUpdate, SQL_BUF_SIZE, + "INSERT IGNORE INTO aliasdomains (domain,alias) VALUES ('%s','%s')", + domain, + alias ); + + vcreate_aliasdomains_table(); + if (mysql_query(&mysql_update,SqlBufUpdate)) { + fprintf(stderr, "vmysql: sql error[m]: %s\n", mysql_error(&mysql_update)); + return(-1); + } + return(0); +} + + +/************************************************************************/ +int vdelete_sql_aliasdomain(char *alias) +{ + int err; + + if ( (err=vauth_open_update()) != 0 ) return(err); + + qnprintf( SqlBufUpdate, SQL_BUF_SIZE, + "DELETE FROM aliasdomains WHERE alias='%s'", + alias ); + + vcreate_aliasdomains_table(); + if (mysql_query(&mysql_update,SqlBufUpdate)) { + fprintf(stderr, "vmysql: sql error[m]: %s\n", mysql_error(&mysql_update)); + return(-1); + } + return(0); +} + diff -ruN ../vpopmail-5.4.33-original/vmysql.h vpopmail-5.4.33/vmysql.h --- ../vpopmail-5.4.33-original/vmysql.h 2011-02-28 18:00:45.000000000 +0100 +++ vpopmail-5.4.33/vmysql.h 2022-08-09 14:04:47.328812970 +0200 @@ -41,21 +41,6 @@ */ -char *MYSQL_READ_SERVER; -int MYSQL_READ_PORT; -char *MYSQL_READ_SOCKET; -char *MYSQL_READ_USER; -char *MYSQL_READ_PASSWD; -char *MYSQL_READ_DATABASE; - -char *MYSQL_UPDATE_SERVER; -int MYSQL_UPDATE_PORT; -char *MYSQL_UPDATE_SOCKET; -char *MYSQL_UPDATE_USER; -char *MYSQL_UPDATE_PASSWD; -int MYSQL_UPDATE_VPORT; -char *MYSQL_UPDATE_DATABASE; - /* defaults - no need to change */ #define MYSQL_DEFAULT_TABLE "vpopmail" #define MYSQL_DOT_CHAR '_' @@ -306,3 +291,12 @@ perm_defaultquota TINYINT(2) NOT NULL DEFAULT 0" #endif +void vcreate_aliasdomains_table(); +int vdelete_sql_aliasdomain(char *alias); +int vcreate_sql_aliasdomain(char *domain, char *alias); + +#define ALIASDOMAINS_TABLE_LAYOUT "alias varchar(100) NOT NULL, \ + domain varchar(100) NOT NULL, \ + PRIMARY KEY (alias)" + +int vcreate_sql_procedures(); diff -ruN ../vpopmail-5.4.33-original/voracle.pc vpopmail-5.4.33/voracle.pc --- ../vpopmail-5.4.33-original/voracle.pc 2011-02-28 18:00:45.000000000 +0100 +++ vpopmail-5.4.33/voracle.pc 2023-02-18 16:14:22.073663686 +0100 @@ -779,7 +779,8 @@ ++ipaddr; } - if ( (err=vauth_open_update()) != 0 ) return; + // open_smtp_relay() expects "-1" on database errors. "0" means duplicate record. (See vpopmail.c) + if ( (err=vauth_open_update()) != 0 ) return (-1); qnprintf( SqlBufUpdate, SQL_BUF_SIZE, "insert into relay ( ip_addr, timestamp ) values ( '%s', %d )", @@ -1442,6 +1443,11 @@ int vdel_limits( char *domain ) { + int err; + + // CHECKS IF A DATABASE CONNECTION IS AVAILABLE, CONNECTS IF NOT. + // THIS CHECK PREVENTS "CORE-DUMP" OF vqadmin.cgi. + if ( (err=vauth_open_update()) != 0 ) return(err); qnprintf( SqlBufUpdate, SQL_BUF_SIZE, "DELETE FROM limits WHERE domain = '%s'", domain); EXEC SQL PREPARE S FROM :SqlBufUpdate; diff -ruN ../vpopmail-5.4.33-original/vpgsql.c vpopmail-5.4.33/vpgsql.c --- ../vpopmail-5.4.33-original/vpgsql.c 2011-02-28 18:00:45.000000000 +0100 +++ vpopmail-5.4.33/vpgsql.c 2023-02-18 16:15:11.296521575 +0100 @@ -392,10 +392,10 @@ #endif #ifdef ENABLE_SQL_LOGGING - qnprintf( sqlBufUpdate, SQL_BUF_SIZE, + qnprintf( SqlBufUpdate, SQL_BUF_SIZE, "delete from vlog where domain = '%s'", domain ); pgres=PQexec(pgc, SqlBufUpdate); - if( !pgres || PGresultStatus(pgres)!=PGRES_COMMAND_OK) { + if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK) { return(-1); } #endif @@ -445,11 +445,11 @@ #endif #ifdef ENABLE_SQL_LOGGING - qnprintf( sqlBufUpdate, SQL_BUF_SIZE, + qnprintf( SqlBufUpdate, SQL_BUF_SIZE, "delete from vlog where domain = '%s' and user='%s'", domain, user ); pgres=PQexec(pgc, SqlBufUpdate); - if( !pgres || PGresultStatus(pgres)!=PGRES_COMMAND_OK) { + if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK) { err = -1; } #endif @@ -771,8 +771,9 @@ PGresult *pgres; time_t delete_time; int err; - - if ( (err=vauth_open(1)) != 0 ) return; + + // open_smtp_relay() expects "-1" on database errors. "0" means duplicate record. (See vpopmail.c) + if ( (err=vauth_open(1)) != 0 ) return (-1); delete_time = mytime - clear_minutes; snprintf( SqlBufUpdate, SQL_BUF_SIZE, diff -ruN ../vpopmail-5.4.33-original/vpopmail.c vpopmail-5.4.33/vpopmail.c --- ../vpopmail-5.4.33-original/vpopmail.c 2011-02-28 18:00:45.000000000 +0100 +++ vpopmail-5.4.33/vpopmail.c 2022-08-09 14:04:47.330812965 +0200 @@ -147,7 +147,16 @@ char Dir[MAX_BUFF]; int call_dir; string_list aliases; - + char ch, defaultdelivery_file[MAX_BUFF]; + FILE *defaultdelivery; + int default_delivery_option; + +#ifdef DEFAULT_DELIVERY + default_delivery_option = 1; +#else + default_delivery_option = 0; +#endif + #ifdef ONCHANGE_SCRIPT /* Don't execute any implied onchange in called functions */ allow_onchange = 0; @@ -269,10 +278,27 @@ dec_dir_control(dir_control_for_uid, uid, gid); fchdir(call_dir); close(call_dir); return(VA_COULD_NOT_OPEN_QMAIL_DEFAULT); + } else if ( default_delivery_option == 1 ) { + + /* Copy the content of control/defaultdelivery into .qmail-default */ + + snprintf(defaultdelivery_file, sizeof(defaultdelivery_file), "%s/control/defaultdelivery", QMAILDIR); + defaultdelivery = fopen(defaultdelivery_file, "r"); + if( defaultdelivery == NULL ) + { + printf("\nERROR: Missing %s/control/defaultdelivery file.\n", QMAILDIR); + printf("To create a %s/control/defaultdelivery file type:\n", QMAILDIR); + printf("echo \"| %s/bin/vdelivermail '' delete\" > %s/control/defaultdelivery\n\n", VPOPMAILDIR, QMAILDIR); + exit(EXIT_FAILURE); + } + + while ( ( ch = fgetc(defaultdelivery) ) != EOF ) fputc(ch, fs); + + fclose(defaultdelivery); } else { - fprintf(fs, "| %s/bin/vdelivermail '' bounce-no-mailbox\n", VPOPMAILDIR); - fclose(fs); + fprintf(fs, "| %s/bin/vdelivermail '' delete\n", VPOPMAILDIR); } + fclose(fs); /* create an entry in the assign file for our new domain */ snprintf(tmpbuf, sizeof(tmpbuf), "%s/%s/%s", dir, DOMAINS_DIR, DomainSubDir); @@ -554,6 +580,14 @@ fprintf (stderr, "Warning: Failed to delete domain from the assign file\n"); } +#ifdef SQL_ALIASDOMAINS + /* aliasdomain table will eventually be created */ + for(i=0; i /var/qmail/control/recipients + + * @file vrcptcheck.c + @return 0: virtual user exists + 1: virtual user does not exist + 111: temporary problem + */ + +#include +#include +#include +#include +#include +#include "vpopmail.h" + +#define FDAUTH 3 +char inputbuf[MAX_BUFF]; + +void pam_exit(int fail, DIR *dir) +{ + int i; + close(FDAUTH); + for (i = 0; i < sizeof(inputbuf); ++i) inputbuf[i] = 0; + if (dir != NULL) closedir(dir); + vexit(fail); +} + +void main(int argc, char *argv[]) +{ + char path[MAX_BUFF]; + DIR *dir; + + /* read input */ + if (read(FDAUTH, inputbuf, sizeof(inputbuf)) == -1) + { + fprintf(stderr, "qmail-smtpd: Error while reading file descriptor in vrcptcheck\n"); + pam_exit(111,NULL); + } + close(FDAUTH); + + /* retrieve username/domain (assuming that MAV has already been done) */ + int i = 0; + char *p = strtok (inputbuf, "@"); + char *recipient[2]; + while (p != NULL) + { + recipient[i++] = p; + p = strtok (NULL, "@"); + } + + /* recipient check */ + snprintf(path, MAX_BUFF, "%s/%s", vget_assign(recipient[1], NULL, 0, NULL, NULL), recipient[0]); + dir = opendir(path); + if (dir) pam_exit(0, dir); + else pam_exit(1, dir); +} diff -ruN ../vpopmail-5.4.33-original/vsavealiasdomains.c vpopmail-5.4.33/vsavealiasdomains.c --- ../vpopmail-5.4.33-original/vsavealiasdomains.c 1970-01-01 01:00:00.000000000 +0100 +++ vpopmail-5.4.33/vsavealiasdomains.c 2022-08-09 14:04:47.331812963 +0200 @@ -0,0 +1,251 @@ +/* + * $Id: vsavealiasdomains.c 2021-02-15 + * Roberto Puzzanghera - https://notes.sagredo.eu + * + * 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 + */ + +/* + * This program can be useful to quickly create domain aliases records in the aliasdomains MySQL table + * when switching to the dovecot's sql driver. + * + * To save ALL your existing aliasdomains to MySQL just do like this: + * + * vsavealiasdomain -A + * + * Type 'vsavealiasdomain -h' for more options. + * + * Look at the documentation concerning the sql-aliasdomains feature in the doc/README.sql-aliasdomains file + * or at https://notes.sagredo.eu/en/qmail-notes-185/dovecot-vpopmail-auth-driver-removal-migrating-to-the-sql-driver-241.html + * web page. + */ + +#include +#include +#include +#include +#include "config.h" +#include "vpopmail.h" +#include "vauth.h" + +char Domain[MAX_BUFF]; +char Alias[MAX_BUFF]; +int SaveAll; + +void usage(); +void get_options(int argc, char **argv); +void save_all_aliases(); +void save_one_real_domain_aliases( char *Domain ); +void save_alias( char *Domain, char *Alias ); +#ifndef SQL_ALIASDOMAINS +int vcreate_sql_aliasdomain(char *Domain, char *Alias); +#endif + +int main(int argc, char *argv[]) +{ + if( vauth_open( 0 )) { + vexiterror( stderr, "Initial open." ); + } + +#ifndef SQL_ALIASDOMAINS + printf("\nPlease use option --enable-sql-aliasdomains at configure time\n\n"); + exit(-1); +#else + get_options(argc,argv); + + /* did we want to save all aliases of one single domain? */ + if ( Domain[0] > 0 && Alias[0] == 0 ) { + save_one_real_domain_aliases( Domain ); + } + /* did we want to save just an alias of a particular domain? */ + else if ( Domain[0] > 0 && Alias[0] > 0 ) { + save_alias( Domain, Alias ); + } + /* save all aliases of all domains */ + else if ( SaveAll == 1 ) { + save_all_aliases(); + } + else { + usage(); + } + return(vexit(0)); +#endif +} + +void usage() +{ + printf("\nUsage: vsavealiasdomains [options] [real_domain] [alias_domain]\n"); + printf("options: -v (print version number)\n"); + printf(" -h (help)\n"); + printf(" -A (saves all aliases of all domains to MySQL)\n"); + printf("vsavealiasdomains domain (saves all aliases of a domain to MySQL)\n"); + printf("vsavealiasdomains real_domain alias_domain (saves an alias domain to MySQL)\n\n"); +} + +void get_options(int argc, char **argv) +{ + int c; + int errflag; + extern int optind; + + SaveAll = 0; + + memset(Domain, 0, sizeof(Domain)); + + errflag = 0; + while( !errflag && (c=getopt(argc,argv,"vAh")) != -1 ) { + switch(c) { + case 'v': + printf("version: %s\n", VERSION); + break; + + case 'A': + SaveAll = 1; + break; + + case 'h': + errflag = 1; + break; + + default: + errflag = 1; + break; + } + } + + if ( errflag > 0 ) { + usage(); + vexit(-1); + } + + if ( optind < argc ) { + snprintf(Domain, sizeof(Domain), "%s", argv[optind]); + ++optind; + } + + if ( optind < argc ) { + snprintf(Alias, sizeof(Alias), "%s", argv[optind]); + ++optind; + } + + if ( Domain[0]>0 && Alias[0]>0 && strcmp( Domain, Alias ) == 0 ) { + printf("Error: real domain and alias domain are the same!\n"); + usage(); + vexit(-1); + } +} + +#ifdef SQL_ALIASDOMAINS +/* + * Save all aliases of all real domains to database + */ +void save_all_aliases() +{ + domain_entry *entry; + entry = get_domain_entries(""); + + if (entry==NULL) { + if( verrori ) { + printf("Can't get domain entries - %s\n", verror( verrori )); + vexit(-1); + } else { + printf("No domain found\n"); + vexit(0); + } + } + + int i = 0; + while( entry ) { + /* we won't save realdomain/realdomain pairs */ + if ( strcmp(entry->realdomain,entry->domain) != 0 ) { + vcreate_sql_aliasdomain(entry->realdomain, entry->domain); + printf ("Alias: %s Real domain: %s saved\n", entry->domain, entry->realdomain); + ++i; + } + entry = get_domain_entries(NULL); + } + if ( i == 0 ) { + printf ("No aliases found\n"); + } +} + + +/* + * Save all aliases of domain Domain to database + */ +void save_one_real_domain_aliases( char *Domain ) +{ + domain_entry *entry; + entry = get_domain_entries ( Domain ); + + if (entry==NULL) { + if( verrori ) { + printf("Can't get domain entries - %s\n", verror( verrori )); + vexit(-1); + } else { + printf("%s does not exist\n", Domain); + vexit(0); + } + } + + int i = 0; + while( entry ) { + /* we won't save realdomain/realdomain pairs */ + if ( strcmp(entry->realdomain,entry->domain) != 0 ) { + vcreate_sql_aliasdomain(entry->realdomain, entry->domain); + printf ("Alias: %s Real domain: %s saved\n", entry->domain, entry->realdomain); + i++; + } + entry = get_domain_entries(NULL); + } + if ( i == 0 ) { + printf ("No aliases found for domain %s\n", Domain); + } +} + + +/* + * Save the pair Alias/Domain to database + */ +void save_alias( char *Domain, char *Alias ) +{ + domain_entry *entry; + entry = get_domain_entries ( Domain ); + + if (entry==NULL) { + if( verrori ) { + printf("Can't get domain entries - %s\n", verror( verrori )); + vexit(-1); + } else { + printf("%s does not exist\n", Domain); + vexit(0); + } + } + + int i = 0; + while( entry ) { + /* we won't save realdomain/realdomain pairs */ + if ( strcmp(Alias,entry->domain) == 0 && strcmp(entry->realdomain,entry->domain) != 0 ) { + vcreate_sql_aliasdomain(entry->realdomain, entry->domain); + printf ("Alias: %s Real domain: %s saved\n", entry->domain, entry->realdomain); + i++; + } + entry = get_domain_entries(NULL); + } + if ( i == 0 ) { + printf ("No alias %s found for domain %s\n", Alias, Domain); + } +} +#endif diff -ruN ../vpopmail-5.4.33-original/vusaged/configure.ac vpopmail-5.4.33/vusaged/configure.ac --- ../vpopmail-5.4.33-original/vusaged/configure.ac 2011-02-28 18:00:45.000000000 +0100 +++ vpopmail-5.4.33/vusaged/configure.ac 2022-08-09 14:04:47.331812963 +0200 @@ -392,17 +392,17 @@ if test x"$ac_cv_lib_vpopmail_vauth_getpw" = xno then - AC_MSG_ERROR([No vauth_getpw in libvpopmail]) + AC_MSG_RESULT([No vauth_getpw in libvpopmail]) fi if test x"$ac_cv_lib_vpopmail_vauth_getall" = xno then - AC_MSG_ERROR([No vauth_getall in libvpopmail]) + AC_MSG_RESULT([No vauth_getall in libvpopmail]) fi if test x"$ac_cv_lib_vpopmail_get_domain_entries" = xno then - AC_MSG_ERROR([No get_domain_entires in libvpopmail]) + AC_MSG_RESULT([No get_domain_entires in libvpopmail]) fi if test x"$ac_cv_lib_vpopmail_client_query_quick" = xno diff -ruN ../vpopmail-5.4.33-original/vuserinfo.c vpopmail-5.4.33/vuserinfo.c --- ../vpopmail-5.4.33-original/vuserinfo.c 2011-02-28 18:00:45.000000000 +0100 +++ vpopmail-5.4.33/vuserinfo.c 2023-03-02 11:36:36.595745033 +0100 @@ -111,6 +111,8 @@ while( (mypw=vauth_getall(Domain, first, 1))) { first = 0; /* display each user in the domain */ + /* When all users of a domain are displayed, print a new line to recognize where each user's info starts/ends */ + printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"); display_user(mypw, Domain); } }