v. 2023.11.11 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 https://notes.sagredo.eu/en/qmail-notes-185/a-valias-forward-compatible-with-sieve-solution-for-qmail-new-patches-and-roundcube-plugin-301.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 * defauldelivery patch Normally vpopmail copies its delivery agent vdelivermail into the .qmail-default file of newly created domains. Changing the delivery agent vdelivermail in the .qmail-default file will get your system to gain the sieve rules functionality by dovecot, for instance. But in this case the valiases stored in MySQL will no longer be recognized. Having the vpopmail's vdelivermail into the .qmail-default and the dovecot (or whatelse) delivery agent in the user's .qmail will preserve the virtual aliases, which will be handled by vpopmail in the .qmail-default file, but will get your favorite LDA to be called from within the mailbox .qmail file. In addition, having the aliases on MySQL is a benefit as you can build plugins for RoundCube (or your favorite webmail) to handle them. And, last but not least, letting vpopmail to handle your aliases instead of a sieve rule will make qmail to rewrite the sender address (SRS) and preserve the SPF validity of the original sender. This patch will get the qmail/vpopmail system to achieve this. It makes vpopmail to copy your favourite delivery agent, stored in QMAILDIR/control/defauldelivery in the mailbox's .qmail. In addition, this patch makes vdelivermail to be installed in .qmail-default with the "delete" option instead of "bounce-no-mailbox", which is not reasonable anymore. https://notes.sagredo.eu/en/qmail-notes-185/a-valias-forward-compatible-with-sieve-solution-for-qmail-new-patches-and-roundcube-plugin-301.html 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 "s/qmail cdb" patch for s/qmail users who have the QMAILDIR/users/cdb moved to QMAILDIR/users/assign.cdb. You can enable for vpopmail to look for the correct cdb file at configure time: Default option is disabled * 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 2023-08-18 07:17:58.321799402 +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,8 @@ 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 \ + vmakedotqmail vusagec_SOURCES = vusagec.c client.c conf.c ippp.c vusagec_LDADD = libvpopmail.a @auth_libs@ @@ -114,6 +116,15 @@ vmoddomlimits_SOURCES = vmoddomlimits.c vmoddomlimits_LDADD = libvpopmail.a @auth_libs@ +vsavealiasdomains_SOURCES = vsavealiasdomains.c +vsavealiasdomains_LDADD = libvpopmail.a @auth_libs@ + +vmakedotqmail_SOURCES = vmakedotqmail.c +vmakedotqmail_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 +160,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 2023-10-13 19:35:03.130943350 +0200 @@ -381,6 +381,27 @@ AC_DEFINE_UNQUOTED(QMAILNEWMRH,"$qmailnewmrh","") #---------------------------------------------------------------------- +AC_MSG_CHECKING(whether we have to deal with assign.cdb file) +AC_ARG_ENABLE(sqmail-cdb, + [ --disable-sqmail-cdb If using s/qmail, vpopmail looks for qmail/users/assign.cdb instead of qmail/users/cdb (default disabled).], + SQMAILCDB=$enableval, + [ + SQMAILCDB=n + ] +) + +case $SQMAILCDB in + 1*|y*|Y*) + AC_MSG_RESULT(yes) + SQMAILCDB=1 + AC_DEFINE_UNQUOTED(SQMAILCDB,$SQMAILCDB,"") + ;; + *) + AC_MSG_RESULT(no) + ;; +esac + +#---------------------------------------------------------------------- AC_MSG_CHECKING(for valid vpopmail user and group) @@ -1454,6 +1475,29 @@ ;; esac + +#---------------------------------------------------------------------- + +AC_MSG_CHECKING(whether defaultdelivery is enabled) +AC_ARG_ENABLE(defaultdelivery, + [ --enable-defaultdelivery Copy the content of control/defaultdelivery to ~mailbox/.qmail on user 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 +1528,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 +1968,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 +1988,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" @@ -1866,6 +2016,15 @@ ;; esac +case $SQMAILCDB in + 1*|y*|Y*) + echo " sqmail-cdb = ON --enable-sqmail-cdb" + ;; + *) + echo " sqmail-cdb = OFF --disable-sqmail-cdb" + ;; +esac + echo "${CC} -O2" > cdb/conf-cc echo "${CC} -s" > cdb/conf-ld 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 2023-08-21 16:39:43.867188055 +0200 @@ -0,0 +1,47 @@ +version 2023.08.21 + +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. Changing the delivery agent vdelivermail in the .qmail-default file will get your system to gain +the sieve rules functionality by dovecot, for instance. But in this case the valiases stored in MySQL will +no longer be recognized. + +Having the vpopmail's vdelivermail into the .qmail-default and the dovecot (or whatelse) delivery agent in the +user's .qmail will preserve the virtual aliases, which will be handled by vpopmail in the .qmail-default file, +but will get your favorite LDA to be called from within the mailbox .qmail file. + +In addition, having the aliases on MySQL is a benefit as you can build plugins for RoundCube (or your favorite +webmail) to handle them. And, last but not least, letting vpopmail to handle your aliases instead of a sieve rule +will make qmail to rewrite the sender address (SRS) and preserve the SPF validity of the original sender. + +This patch will get the qmail/vpopmail system to achieve this. It makes vpopmail to copy your favourite +delivery agent, stored in QMAILDIR/control/defauldelivery in the mailbox's .qmail. + +In addition, this patch makes vdelivermail to be installed in .qmail-default with the "delete" option instead of +"bounce-no-mailbox", which is not reasonable anymore. + +The vmakedotqmail program will help you in the transition. It will populate/restore all your .qmail files for +you. Have a look to it: + +vmakedotqmail -h for more info. + +== Settings + +An autoreconf is needed as I modified the original configure.in and Makefile.am files. + +Configure as follows: + +cd vpopmail-src-dir +patch -p1 < patchfile.patch +autoreconf -f -i +./configure --enable-defaultdelivery (default OFF) + +== Looking for the old patch? + +If you like to have the old vpopmail-defaultdelivery patch of mine, which installs the defaultdelivery in +.qmail-default, look here: +https://notes.sagredo.eu/files/qmail/patches/vpopmail/vpopmail-5.4.33-defaultdelivery-domains.patch 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.sqmail-cdb vpopmail-5.4.33/doc/README.sqmail-cdb --- ../vpopmail-5.4.33-original/doc/README.sqmail-cdb 1970-01-01 01:00:00.000000000 +0100 +++ vpopmail-5.4.33/doc/README.sqmail-cdb 2023-10-13 19:35:03.130943350 +0200 @@ -0,0 +1,11 @@ +vpopmail-sqmail-cdb 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 + +============================================================================================================== + +Patch for s/qmail users who have the QMAILDIR/users/cdb moved to QMAILDIR/users/assign.cdb. +You can enable for vpopmail to look for the correct cdb file at configure time: + +--enable-sqmail-cdb + +Default option is disabled 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/vaddaliasdomain.c vpopmail-5.4.33/vaddaliasdomain.c --- ../vpopmail-5.4.33-original/vaddaliasdomain.c 2011-02-28 18:00:45.000000000 +0100 +++ vpopmail-5.4.33/vaddaliasdomain.c 2023-06-03 14:43:33.310581217 +0200 @@ -49,12 +49,12 @@ get_options(argc,argv); - /* see if Domain_a or Domain_b exist */ + /* Check if Domain_a or Domain_b exist */ /* Also, if domain is an alias, convert it to the real domain */ doma = vget_assign(Domain_a, NULL, 0, NULL, NULL); domb = vget_assign(Domain_b, NULL, 0, NULL, NULL); - /* Check if both domains exists */ + /* Check if both domains exist */ if ((doma != NULL) && (domb != NULL)) { printf("Error: Both domains already exist, unable to create alias.\n"); diff -ruN ../vpopmail-5.4.33-original/valias.c vpopmail-5.4.33/valias.c --- ../vpopmail-5.4.33-original/valias.c 2011-02-28 18:00:45.000000000 +0100 +++ vpopmail-5.4.33/valias.c 2023-08-27 11:54:48.621470253 +0200 @@ -65,7 +65,11 @@ if ( strstr(Email, "@") == NULL ) { /* display all aliases for domain */ tmpalias = valias_select_all( Alias, Email ); - if (tmpalias == NULL) vexit(-1); + if (tmpalias == NULL) { + printf("No aliases found for domain %s\n", Email); + fflush(stdout); + vexit(-1); + } while (tmpalias != NULL ) { printf("%s@%s -> %s\n", Alias, Email, tmpalias); fflush(stdout); @@ -74,7 +78,10 @@ } else { /* display aliases for Alias@Domain */ tmpalias = valias_select( Alias, Domain ); - if (tmpalias == NULL) vexit(-1); + if (tmpalias == NULL) { + printf("No aliases %s@%s found\n", Alias, Domain); + vexit(-1); + } while (tmpalias != NULL ) { printf("%s@%s -> %s\n", Alias, Domain,tmpalias); tmpalias = valias_select_next(); 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/vmakedotqmail.c vpopmail-5.4.33/vmakedotqmail.c --- ../vpopmail-5.4.33-original/vmakedotqmail.c 1970-01-01 01:00:00.000000000 +0100 +++ vpopmail-5.4.33/vmakedotqmail.c 2023-11-11 13:53:41.089439257 +0100 @@ -0,0 +1,469 @@ +/* + * vmakedotqmail v. 1.0.1 (Nov 11, 2023) + * 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 create the user's .qmail file with the content of + * control/defauldelivery. It can also handle domain's .qmail-default files. + * Look at the documentation concerning the defaultdelivery feature in the + * doc/README.defaultdelivery file or at the + * https://notes.sagredo.eu/en/qmail-notes-185/installing-and-configuring-vpopmail-81.html + * web page. + * + * + * Usage: vmakedotqmail [option] [argument] + * + * options: -u install .qmail for the user + * -d install .qmail for all users of domain + * -A install .qmail for all users of all domains + * -o (overwrite) do not skip existing .qmail files. Use with -A|-d|-u + * -r (reverse) remove the existing .qmail files. Use with -A|-d|-u + * -q reinstall the .qmail-default in domain -d + * or in ALL domains (-A). + * -t (testing mode) do not really open or write the .qmail + * -h this help + * + * Existing .qmail files won't be overwritten unless you pass -o + * + * Examples: + * + * Install .qmail-default with vdelivermail (delete option) for domain 'domain.tld' + * vmakedotqmail -d domain.tld -q default + * + * Install .qmail-default with your favourite LDA for all domains + * vmakedotqmail -A -q "My LDA instruction as quoted argument here" + */ + +#include +#include +#include +#include +#include +#include "config.h" +#include "vauth.h" +#include "vpopmail.h" + +#define DOT_QMAIL_DEFAULT_OPTION "delete" +#define AUTH_SIZE 156 +int overwriting = 0; +int reverse = 0; +int testing = 0; +char *qValue = NULL; +char *dValue = NULL; + + +/********************************************************** + * retrieve user's homedir + * + * user = input username + * domain = input domain + * homedir = output home directory + * + * @return 0 on success + * -1 on error + **********************************************************/ +int get_homedir(char *user, char *domain, char *homedir) { + struct vqpasswd *mypw; + if ((mypw = vauth_getpw(user, domain)) == NULL) { + if (domain[0] == 0 || strlen(domain)==0) printf("no such domain %s\n", domain); + else printf("no such user %s@%s\n", user, domain); + vexit(-1); + } + snprintf(homedir, MAX_BUFF, "%s", mypw->pw_dir); + + return 0; +} + + +/***************************************************************************************** + * create the .qmail file + * + * homedir = user's home directory where to save the .qmail file + * + * @return 0 on success + * 1 skip, .qmail already exists + * 2 .qmail already exists but overwriting + * 3 .qmail removed + * -1 on error (missing control/defaultdelivery) + * VA_COULD_NOT_OPEN_DOT_QMAIL (-19) on .qmail read error + *****************************************************************************************/ +int make_dotqmail(char *homedir) { + int overwritingFlag = 0; + FILE *fs; + char tmpbuf[MAX_BUFF]; + char ch, defaultdelivery_file[MAX_BUFF]; + FILE *defaultdelivery; + + // exit if control/defaultdelivery already has vdelivermail, to avoid vpopmail loop + if (!reverse) { + snprintf(defaultdelivery_file, sizeof(defaultdelivery_file), "%s/control/defaultdelivery", QMAILDIR); + defaultdelivery = fopen(defaultdelivery_file, "r"); + while((fgets(tmpbuf, MAX_BUFF, defaultdelivery)!=NULL)) { + if(strstr(tmpbuf, "vdelivermail")!=NULL) { + return 4; + break; + } + } + rewind(defaultdelivery); + } + + // build .qmail path + snprintf(tmpbuf, sizeof(tmpbuf), "%s/.qmail", homedir); + // return if file exists already unless -r removing. Continue if overwriting is active + if (access(tmpbuf, F_OK)==0 && !reverse) { + // exit + if (!overwriting) return 1; + // continue if overwriting, but mark + else overwritingFlag = 1; + } + + // do not touch/remove nor fill the .qmail if testing + if (testing) { + if (overwritingFlag) return 2; + else if (reverse) return 3; + else return 0; + } + + // if -r delete the .qmail + if (reverse && remove(tmpbuf)==-1) { + printf("Unable to remove %s\n", tmpbuf); + exit -1; + } + else if (!reverse) { + // open .qmail + if ((fs = fopen(tmpbuf, "w+"))==NULL) { + printf("Could not open %s\n", tmpbuf); + vexit(VA_COULD_NOT_OPEN_DOT_QMAIL); + } + /* setup the permission of the .qmail file */ + chown(tmpbuf, VPOPMAILUID, VPOPMAILGID); + chmod(tmpbuf, 0600); + + /* Copy the content of control/defaultdelivery into ~userhomedir/.qmail */ + 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 type:\n", QMAILDIR); + printf("echo \"| %s/bin/vdelivermail '' delete\" > %s/control/defaultdelivery\n\n", VPOPMAILDIR, QMAILDIR); + vexit(-1); + } + + while ((ch = fgetc(defaultdelivery)) != EOF) fputc(ch, fs); + + fclose(defaultdelivery); // close control/defaultdelivery + fclose(fs); // close .qmail + } + + if (overwritingFlag) return 2; + else if (reverse) return 3; + else return 0; +} + + +/********************************************************** + * Rebuild the .qmail-default on each domain with the + * + * domain = input domain + * option = - preferred LDA instruction + * - default (install vdelivermail with delete option) + * + * @return 0 on success + * -1 on error + **********************************************************/ +int make_dotqmail_default(char *domain) { + FILE *fs; + char tmpbuf[MAX_BUFF]; + char ldabuf[MAX_BUFF]; + char ch; + char *realdomain = vget_assign(domain, NULL, 0, NULL, NULL); // path of real domain + + // the lda will be vdelivermail if -q default + if (strcmp(qValue, "default")==0) snprintf(ldabuf, sizeof(ldabuf), "| %s/bin/vdelivermail '' %s", VPOPMAILDIR, DOT_QMAIL_DEFAULT_OPTION); + else snprintf(ldabuf, sizeof(ldabuf), "%s", qValue); + + /* process domain */ + printf("%s: rewriting .qmail-default: \"%s\": ", domain, ldabuf); + snprintf(tmpbuf, sizeof(tmpbuf), "%s/.qmail-default", realdomain); + + // do not rewrite the .qmail-default if testing + if (testing) { + printf("**TESTING**\n"); + return 0; + } + + // open .qmail-default + if ((fs = fopen(tmpbuf, "w+"))==NULL) { + printf("Could not open %s\n", tmpbuf); + return VA_COULD_NOT_OPEN_DOT_QMAIL; + } + /* setup the permission of the .qmail file */ + chown(tmpbuf, VPOPMAILUID, VPOPMAILGID); + chmod(tmpbuf, 0600); + + // write the contents in .qmail-default + fprintf(fs, "%s", ldabuf); + + // close .qmail-default + fclose(fs); + + printf("DONE\n"); + + return 0; +} + + +/********************************************************** + * Make the job for a specific mailbox + * + * address = input email address + * + * @return 0 on success + * -1 on error + **********************************************************/ +int make_mailbox(char *address) { + char user[AUTH_SIZE]; + char domain[AUTH_SIZE]; + char homedir[MAX_BUFF]; + int i; + char *teststr = (testing) ? "**TESTING** " : ""; + + memset (homedir, 0, MAX_BUFF); + + if( (parse_email(address, user, domain, AUTH_SIZE)) == 0 ) { + if (domain[0] == 0 || strlen(domain)==0) { + printf("missing domain\n"); + exit(-1); + } + // get user's home directory + get_homedir(user, domain, homedir); + // install qmail in user's home dir + if ((i = make_dotqmail(homedir))==0) printf("%s%s DONE\n", teststr, address); + else if (i == 4) printf("%s%s SKIP (control/defaultdelivery already has vdelivermail)\n", teststr, address); + else if (i == 3) printf("%s%s REMOVED existing .qmail\n", teststr, address); + else if (i == 2) printf("%s%s DONE (existing .qmail overwritten)\n", teststr, address); + else if (i == 1) printf("%s%s SKIP (.qmail already exists)\n", teststr, address); + } + else exit(-1); + + return 0; +} + + +/********************************************************** + * Make the job for all mailboxes of a specific domain + * + * domain = input domain + * + * @return 0 on success + * -1 on error + **********************************************************/ +int make_domain(char *domain) { + static struct vqpasswd *mypw; + char address[AUTH_SIZE]; + int first = 1; + domain_entry *entry; + + printf("==================================================================\n"); + printf("Domain: %s\n\n", domain); + + // id -d passed check if exists (check already done if -A) + if (dValue) { + entry = get_domain_entries(domain); + // check if the domain exists + if (entry == NULL) { + if (verrori) { + printf("Error: Can't get domain entries - %s\n", verror(verrori)); + exit(verrori); + } + else { + printf("Error: Domain %s does not exist\n\n", domain); + exit(-1); + } + } + } + + // if -q was found make the .qmail-default + if (qValue) make_dotqmail_default(domain); + // else proceed to make the mailbox's .qmail + else { + while (mypw = vauth_getall(domain, first, 1)) { + first = 0; + // build the mailbox address + sprintf(address, "%s@%s", mypw->pw_name, domain); + make_mailbox(address); + } + } + printf("==================================================================\n\n"); + return 0; +} + + +/********************************************************** + * Make the job for all mailboxes of all domains + * + * @return 0 on success + * -1 on error + **********************************************************/ +int make_all_domains() { + domain_entry *entry; + entry = get_domain_entries(""); + + if (entry == NULL) { + printf("Something went wrong on domain_entry (err 51)\n"); + return -1; + } + while (entry) { + /* we won't process domain aliases */ + if (!strcmp(entry->realdomain, entry->domain)) { + /* process domain */ + make_domain(entry->domain); + } + else { + printf("==================================================================\n"); + printf("SKIP domain: %s (alias of %s)\n", entry->domain, entry->realdomain); + printf("==================================================================\n\n"); + } + entry = get_domain_entries(NULL); + } + return 0; +} + + +void usage() +{ + printf("\n"); + printf("Usage: vmakedotqmail [option] [argument]\n\n"); + + printf("options: -u install .qmail for the user \n"); + printf(" -d install .qmail for all users of domain \n"); + printf(" -A install .qmail for all users of all domains\n"); + printf(" -o (overwrite) do not skip existing .qmail files. Use with -A|-d|-u\n"); + printf(" -r (reverse) remove the existing .qmail files. Use with -A|-d|-u\n"); + printf(" -q [default|argument] reinstall the .qmail-default in domain -d \n"); + printf(" or in ALL domains (-A).\n"); + printf(" -t (testing mode) do not really open or write the .qmail\n"); + printf(" -h this help\n\n"); + + printf("Existing .qmail files won't be overwritten unless you pass -o\n\n"); + + printf("Examples:\n\n"); + + printf("\tInstall control/defaultdelivery to .qmail of all mailboxes of all domain (overwrite -o active)\n"); + printf("\tvmakedotqmail -o -A\n\n"); + + printf("\tInstall control/defaultdelivery to .qmail of user (skip if existing)\n"); + printf("\tvmakedotqmail -o -u \n\n"); + + printf("\tInstall .qmail-default with vdelivermail (delete option) for domain 'domain.tld'\n"); + printf("\tvmakedotqmail -d domain.tld -q default\n\n"); + + printf("\tInstall .qmail-default with vdelivermail (delete option) for domain 'domain.tld'\n"); + printf("\tvmakedotqmail -d domain.tld -q default\n\n"); + + printf("\tInstall .qmail-default with your favourite LDA for all domains\n"); + printf("\tvmakedotqmail -A -q \"My LDA instruction as quoted argument here\"\n\n"); +} + + +int make(int argc, char *argv[]) +{ + int c; + int errFlag = 0; + int AFlag = 0; + char *uValue = NULL; + + while((c=getopt(argc,argv,"aAu:d:q:orth")) != -1) { + switch(c) { + case 'a': + case 'A': + AFlag = 1; + break; + + case 'd': + dValue = optarg; + break; + + case 'u': + uValue = optarg; + break; + + case 'q': + qValue = optarg; + break; + + case 'o': + overwriting = 1; + break; + + case 'r': + reverse = 1; + break; + + case 't': + testing = 1; + break; + + case 'h': + errFlag = 1; + break; + + default: + errFlag = 1; + break; + } + } + + if (errFlag) { + usage(); + return -1; + } + + if (qValue && !AFlag && !dValue) { + printf("If using -q, always pass argument -d or -A (all)\n"); + usage(); + return -1; + } + + if (AFlag) { + dValue = NULL; // overwrites -d + uValue = NULL; // overwrites -u + return make_all_domains(); + } + else if (dValue) { + uValue = NULL; // overwrites -u + return make_domain(dValue); + } + else if (uValue) return make_mailbox(uValue); + else if (qValue == NULL) { + usage(); + return -1; + } +} + + +int main(int argc, char *argv[]) +{ +#ifndef DEFAULT_DELIVERY + printf("\nPlease use option --enable-defaultdelivery at configure time\n\n"); + exit(-1); +#else + exit(make(argc, argv)); +#endif +} 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-08-27 11:50:39.360134609 +0200 @@ -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 )", @@ -1535,6 +1556,8 @@ void vcreate_valias_table() { vauth_create_table ("valias", VALIAS_TABLE_LAYOUT, 1); + // defaultdelivery feature can't work without the new layout, + // so run the upgrade query } @@ -1849,6 +1872,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 +1895,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 2023-08-27 12:25:11.967117767 +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 '_' @@ -259,9 +244,22 @@ level_mod0, level_mod1, level_mod2, \ level_index0, level_index1, level_index2, the_dir" -#define VALIAS_TABLE_LAYOUT "alias char(32) not null, \ -domain char(96) not null, \ -valias_line text not null, index (alias, domain)" +#ifdef DEFAULTDELIVERY +#define VALIAS_TABLE_LAYOUT \ +"valias_type tinyint(1) NOT NULL DEFAULT 1 COMMENT '1=forwarder 0=lda', \ +alias char(32) NOT NULL, \ +domain char(96) NOT NULL, \ +valias_line text NOT NULL, \ +copy tinyint(1) NOT NULL DEFAULT 0 COMMENT '0=redirect 1=copy&redirect', \ +PRIMARY KEY (alias,domain,valias_type), \ +INDEX (alias, domain)" +#else +#define VALIAS_TABLE_LAYOUT "id int(11) PRIMARY KEY AUTO_INCREMENT, \ +alias char(32) NOT NULL, \ +domain char(96) NOT NULL, \ +valias_line text NOT NULL, \ +INDEX (alias, domain)" +#endif #endif @@ -306,3 +304,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 2023-10-23 16:56:40.531636953 +0200 @@ -147,7 +147,7 @@ char Dir[MAX_BUFF]; int call_dir; string_list aliases; - + #ifdef ONCHANGE_SCRIPT /* Don't execute any implied onchange in called functions */ allow_onchange = 0; @@ -270,10 +270,11 @@ fchdir(call_dir); close(call_dir); return(VA_COULD_NOT_OPEN_QMAIL_DEFAULT); } else { - fprintf(fs, "| %s/bin/vdelivermail '' bounce-no-mailbox\n", VPOPMAILDIR); + 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); if (add_domain_assign( domain, domain, tmpbuf, uid, gid ) != 0) { @@ -554,6 +555,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 %s/control/defaultdelivery\n\n", VPOPMAILDIR, QMAILDIR); + vexit(EXIT_FAILURE); + } + + // is_vdelivermail = 1 if defaultdelivery already contains vdelivermail + int is_vdelivermail = 0; + while((fgets(tmpbuf2, MAX_BUFF, defaultdelivery)!=NULL)) { + if(strstr(tmpbuf2, "vdelivermail")!=NULL) { + is_vdelivermail = 1; + break; + } + } + rewind(defaultdelivery); + + while ( ( ch = fgetc(defaultdelivery) ) != EOF ) fputc(ch, fs); + + fclose(defaultdelivery); // close control/defaultdelivery + fclose(fs); // close .qmail + + // if defaultdelivery already contains vdelivermail remove the .qmail file + if (is_vdelivermail == 1) remove(tmpbuf); + } + /*********************** end defauldelivery patch *****************************************************************/ + return(VA_SUCCESS); } @@ -2992,7 +3053,11 @@ snprintf(cdb_key, sizeof(cdb_key), "!%s-", domain); /* work out the location of the cdb file */ +#ifdef SQMAILCDB + snprintf(cdb_file, sizeof(cdb_file), "%s/users/assign.cdb", QMAILDIR); +#else snprintf(cdb_file, sizeof(cdb_file), "%s/users/cdb", QMAILDIR); +#endif /* try to open the cdb file */ if ( (fs = fopen(cdb_file, "r")) == 0 ) { @@ -3772,6 +3837,11 @@ call_onchange ( "add_alias_domain" ); #endif +#ifdef SQL_ALIASDOMAINS + /* aliasdomain table will eventually be created */ + vcreate_sql_aliasdomain(real_domain, alias_domain); +#endif + return(VA_SUCCESS); } diff -ruN ../vpopmail-5.4.33-original/vpopmail.h vpopmail-5.4.33/vpopmail.h --- ../vpopmail-5.4.33-original/vpopmail.h 2011-02-28 18:00:45.000000000 +0100 +++ vpopmail-5.4.33/vpopmail.h 2023-08-21 11:29:16.004674717 +0200 @@ -372,3 +372,6 @@ #ifdef USERS_BIG_DIR char *backfill(char *, char *, char *, int); #endif + +int vcreate_sql_aliasdomain(char *domain, char *alias); +int vdelete_sql_aliasdomain(char *alias); diff -ruN ../vpopmail-5.4.33-original/vrcptcheck.c vpopmail-5.4.33/vrcptcheck.c --- ../vpopmail-5.4.33-original/vrcptcheck.c 1970-01-01 01:00:00.000000000 +0100 +++ vpopmail-5.4.33/vrcptcheck.c 2023-08-16 18:13:21.990451069 +0200 @@ -0,0 +1,78 @@ +/* + * vrcptcheck.c 2021-09-23 + * 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 + */ + +/* + * 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 + + * @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 2023-08-16 18:13:09.262487612 +0200 @@ -0,0 +1,251 @@ +/* + * 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-08-21 16:25:05.949342406 +0200 @@ -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); } }