Este tutorial es Copyright (c) 2010 por Falko Timme. Se deriva de un tutorial de Christoph Haas que puede encontrar en http://workaround.org. Puede utilizar este tutorial bajo la licencia Creative Commons 2.5 o cualquier versión posterior.
Este documento describe cómo instalar un servidor de correo basado en Postfix que se basa en usuarios y dominios virtuales, es decir, usuarios y dominios que están en una base de datos MySQL. También demostraré la instalación y configuración de Courier (Courier-POP3, Courier-IMAP), para que Courier pueda autenticarse contra la misma base de datos MySQL que usa Postfix.
El servidor Postfix resultante es capaz de SMTP-AUTH y TLS y cuota (La cuota no está integrada en Postfix de forma predeterminada, le mostraré cómo parchear su Postfix de manera adecuada). Las contraseñas se almacenan en encriptadas formulario en la base de datos (la mayoría de los documentos que encontré trataban con contraseñas de texto sin formato, lo que es un riesgo de seguridad). Además de eso, este tutorial cubre la instalación de Amavisd , Asesino de spam y ClamAV para que los correos electrónicos sean escaneados en busca de spam y virus. También mostraré cómo instalar SquirrelMail como una interfaz de correo web para que los usuarios puedan leer y enviar correos electrónicos y cambiar sus contraseñas.
La ventaja de una configuración "virtual" de este tipo (usuarios y dominios virtuales en una base de datos MySQL) es que tiene mucho más rendimiento que una configuración basada en usuarios "reales" del sistema. Con esta configuración virtual, su servidor de correo puede manejar miles de dominios y usuarios. Además, es más fácil de administrar porque solo tiene que lidiar con la base de datos MySQL cuando agrega nuevos usuarios/dominios o edita los existentes. No más comandos postmap para crear archivos db, no más recargas de Postfix, etc. Para la administración de la base de datos MySQL, puede usar herramientas basadas en web como phpMyAdmin, que también se instalará en este tutorial. La tercera ventaja es que los usuarios tienen una dirección de correo electrónico como nombre de usuario (en lugar de un nombre de usuario + una dirección de correo electrónico) que es más fácil de entender y tener en cuenta.
Este howto pretende ser una guía práctica; no cubre los antecedentes teóricos. Se tratan en muchos otros documentos en la web.
¡Este documento viene sin garantía de ningún tipo! Quiero decir que esta no es la única forma de establecer un sistema de este tipo. Hay muchas maneras de lograr este objetivo, pero este es el camino que tomo. ¡No emito ninguna garantía de que esto funcione para usted!
1 nota preliminar
Este tutorial se basa en el servidor Ubuntu 10.04 (Lucid Lynx), por lo que debe configurar una instalación básica del servidor Ubuntu 10.04 antes de continuar con este tutorial (por ejemplo, como se muestra en las páginas 1 - 3 de este tutorial:El servidor perfecto - Ubuntu Lucid Lynx (Ubuntu 10.04) [ISPConfig 2]). El sistema debe tener una dirección IP estática. Uso 192.168.0.100 como mi dirección IP en este tutorial y server1.example.com como nombre de host.
Asegúrese de haber iniciado sesión como raíz (escriba
sudo su
para convertirse en root), porque debemos ejecutar todos los pasos de este tutorial como usuario root.
Es muy importante que haga de /bin/sh un enlace simbólico a /bin/bash...
dpkg-reconfigure dash
¿Instalar guión como /bin/sh? <-- No
... y que deshabilites AppArmor:
/etc/init.d/apparmor stop
update-rc.d -f apparmor remove
aptitude remove apparmor apparmor-utils
2 Instale Postfix, Courier, Saslauthd, MySQL, phpMyAdmin
Para instalar Postfix, Courier, Saslauthd, MySQL y phpMyAdmin, simplemente ejecutamos
aptitude install postfix postfix-mysql postfix-doc mysql-client mysql-server courier-authdaemon courier-authlib-mysql courier-pop courier-pop-ssl courier-imap courier-imap-ssl postfix-tls libsasl2-2 libsasl2-modules libsasl2-modules-sql sasl2-bin libpam-mysql openssl phpmyadmin apache2 libapache2-mod-php5 php5 php5-mysql libpam-smbpass
Se le harán algunas preguntas:
Nueva contraseña para el usuario "root" de MySQL:<-- yourrootsqlpassword
Repetir la contraseña para el usuario "root" de MySQL:<-- yourrootsqlpassword
¿Crear directorios para administración basada en web? <-- No
Tipo general de configuración de correo:<-- Sitio de Internet
Nombre de correo del sistema:<-- server1.example.com
Certificado SSL requerido <-- Ok
Servidor web para reconfigurar automáticamente:<-- apache2
¿Configurar base de datos para phpmyadmin con dbconfig-common? <-- No
3 Aplicar el parche de cuota a Postfix
Tenemos que obtener las fuentes de Postfix, parchearlo con el parche de cuota, crear nuevos paquetes .deb de Postfix e instalar esos paquetes .deb:
aptitude build-dep postfix
cd /usr/src
apt-get source postfix
(Asegúrese de usar la versión correcta de Postfix en los siguientes comandos. Tengo instalado Postfix 2.7.0. Puede encontrar su versión de Postfix ejecutando
postconf -d | grep mail_version
La salida debería verse así:
[correo electrónico protegido]:/usr/src# postconf -d | grep mail_version
mail_version =2.7.0
milter_macro_v =$mail_name $mail_version
[email protected]:/usr/src#
)
wget http://vda.sourceforge.net/VDA/postfix-vda-2.7.0.patch
cd postfix-2.7.0
parche -p1 <../postfix-vda-2.7.0 .patch
dpkg-construir paquete
Ahora subimos un directorio, ahí es donde se han creado los nuevos paquetes .deb:
cd ..
El comando
ls -l
te muestra los paquetes disponibles:
[email protected]:/usr/src# ls -l
total 6396
drwxr-xr-x 24 root root 4096 2010-04-29 14:00 linux-headers-2.6.32-21
drwxr-xr-x 7 raíz raíz 4096 2010-04-29 14:00 linux-headers-2.6.32-21-server
drwxr-xr-x 19 raíz raíz 4096 2010-06-04 16 :02 postfix-2.7.0
-rw-r--r-- 1 root src 3700 2010-06-04 16:03 postfix_2.7.0-1_amd64.changes
-rw-r--r -- 1 root src 1418996 2010-06-04 16:03 postfix_2.7.0-1_amd64.deb
-rw-r--r-- 1 root src 240154 2010-06-04 16:00 postfix_2.7.0- 1.diff.gz
-rw-r--r-- 1 root src 1191 2010-06-04 16:00 postfix_2.7.0-1.dsc
-rw-r--r-- 1 root src 3418064 2010-02-18 07:05 postfix_2.7.0.orig.tar.gz
-rw-r--r-- 1 root src 42522 2010-06-04 16:03 postfix-cdb_2. 7.0-1_amd64.deb
-rw-r--r-- 1 root src 146842 2010-06-04 16:03 postfix-dev_2.7.0-1_all.deb
-rw-r--r -- 1 root src 999490 2010-06-04 16:03 postfix-doc_2.7.0-1_all.deb
-rw-r--r-- 1 root src 50142 2010-06-04 16:03 postfix- ldap_2.7.0-1_ amd64.deb
-rw-r--r-- 1 root src 44278 2010-06-04 16:03 postfix-mysql_2.7.0-1_amd64.deb
-rw-r--r-- 1 root src 44304 2010-06-04 16:03 postfix-pcre_2.7.0-1_amd64.deb
-rw-r--r-- 1 root src 44336 2010-06-04 16:03 postfix-pgsql_2. 7.0-1_amd64.deb
-rw-r--r-- 1 root src 59667 2010-03-03 09:32 postfix-vda-2.7.0.patch
[email protected]:/usr /fuente#
Elija los paquetes postfix y postfix-mysql e instálelos así:
dpkg -i postfix_2.7.0-1_amd64.deb postfix-mysql_2.7.0-1_amd64.deb
4 Crea la base de datos MySQL para Postfix/Courier
Ahora creamos una base de datos llamada correo:
mysqladmin -u root -p create mail
A continuación, vamos al shell de MySQL:
mysql -u root -p
En el shell de MySQL, creamos el usuario mail_admin con la contraseña mail_admin_password (reemplácela con su propia contraseña) que tiene privilegios SELECCIONAR, INSERTAR, ACTUALIZAR, ELIMINAR en la base de datos de correo. Este usuario será utilizado por Postfix y Courier para conectarse a la base de datos de correo:
CONCEDER SELECCIONAR, INSERTAR, ACTUALIZAR, ELIMINAR EN EL CORREO.* A 'mail_admin'@'localhost' IDENTIFICADO POR 'mail_admin_password';
CONCEDER SELECCIONAR, INSERTAR, ACTUALIZAR, ELIMINAR EN EL CORREO.* A 'mail_admin'@'localhost. localdomain' IDENTIFICADO POR 'mail_admin_password';
PRIVILEGIOS DE DESCARGA;
Todavía en el shell de MySQL, creamos las tablas que necesitan Postfix y Courier:
USE mail;
CREATE TABLE dominios (
domain varchar(50) NOT NULL,
PRIMARY KEY (domain) )
TYPE=MyISAM;
Reenvíos CREATE TABLE (
origen varchar(80) NOT NULL,
destino TEXT NOT NULL,
PRIMARY KEY (origen) )
TYPE=MyISAM;
CREATE TABLE usuarios (
email varchar(80) NOT NULL,
password varchar(20) NOT NULL,
quota INT(10) DEFAULT '10485760',
CLAVE PRIMARIA (email )
) TYPE=MiISAM;
CREATE TABLE transport (
dominio varchar(128) NOT NULL predeterminado '',
transport varchar(128) NOT NULL predeterminado '',
CLAVE ÚNICA dominio (dominio)
) TIPO =MiISAM;
quit;
Como habrás notado, con la renuncia; hemos dejado el shell de MySQL y estamos de vuelta en el shell de Linux.
Los dominios la tabla almacenará cada dominio virtual para el que Postfix debería recibir correos electrónicos (por ejemplo, example.com ).
dominio | ||
ejemplo.com |
fuente | destino | |
[correo electrónico protegido] | [correo electrónico protegido] |
correo electrónico | contraseña | cuota |
[correo electrónico protegido] | No9.E4skNvGa. ("secreto" en forma encriptada) | 10485760 |
dominio | transporte | |
ejemplo.com | smtp:[1.2.3.4] |
[...] # Instead of skip-networking the default is now to listen only on # localhost which is more compatible and is not less secure. #bind-address = 127.0.0.1 [...] |
user = mail_admin password = mail_admin_password dbname = mail query = SELECT domain AS virtual FROM domains WHERE domain='%s' hosts = 127.0.0.1 |
user = mail_admin password = mail_admin_password dbname = mail query = SELECT destination FROM forwardings WHERE source='%s' hosts = 127.0.0.1 |
user = mail_admin password = mail_admin_password dbname = mail query = SELECT CONCAT(SUBSTRING_INDEX(email,'@',-1),'/',SUBSTRING_INDEX(email,'@',1),'/') FROM users WHERE email='%s' hosts = 127.0.0.1 |
user = mail_admin password = mail_admin_password dbname = mail query = SELECT email FROM users WHERE email='%s' hosts = 127.0.0.1 |
user = mail_admin password = mail_admin_password dbname = mail query = SELECT transport FROM transport WHERE domain='%s' hosts = 127.0.0.1 |
user = mail_admin password = mail_admin_password dbname = mail query = SELECT quota FROM users WHERE email='%s' hosts = 127.0.0.1 |
# # Settings for saslauthd daemon # Please read /usr/share/doc/sasl2-bin/README.Debian for details. # # Should saslauthd run automatically on startup? (default: no) START=yes # Description of this saslauthd instance. Recommended. # (suggestion: SASL Authentication Daemon) DESC="SASL Authentication Daemon" # Short name of this saslauthd instance. Strongly recommended. # (suggestion: saslauthd) NAME="saslauthd" # Which authentication mechanisms should saslauthd use? (default: pam) # # Available options in this Debian package: # getpwent -- use the getpwent() library function # kerberos5 -- use Kerberos 5 # pam -- use PAM # rimap -- use a remote IMAP server # shadow -- use the local shadow password file # sasldb -- use the local sasldb database file # ldap -- use LDAP (configuration is in /etc/saslauthd.conf) # # Only one option may be used at a time. See the saslauthd man page # for more information. # # Example: MECHANISMS="pam" MECHANISMS="pam" # Additional options for this mechanism. (default: none) # See the saslauthd man page for information about mech-specific options. MECH_OPTIONS="" # How many saslauthd processes should we run? (default: 5) # A value of 0 will fork a new process for each connection. THREADS=5 # Other options (default: -c -m /var/run/saslauthd) # Note: You MUST specify the -m option or saslauthd won't run! # # WARNING: DO NOT SPECIFY THE -d OPTION. # The -d option will cause saslauthd to run in the foreground instead of as # a daemon. This will PREVENT YOUR SYSTEM FROM BOOTING PROPERLY. If you wish # to run saslauthd in debug mode, please run it by hand to be safe. # # See /usr/share/doc/sasl2-bin/README.Debian for Debian-specific information. # See the saslauthd man page and the output of 'saslauthd -h' for general # information about these options. # # Example for postfix users: "-c -m /var/spool/postfix/var/run/saslauthd" #OPTIONS="-c -m /var/run/saslauthd" OPTIONS="-c -m /var/spool/postfix/var/run/saslauthd -r" |
auth required pam_mysql.so user=mail_admin passwd=mail_admin_password host=127.0.0.1 db=mail table=users usercolumn=email passwdcolumn=password crypt=1 account sufficient pam_mysql.so user=mail_admin passwd=mail_admin_password host=127.0.0.1 db=mail table=users usercolumn=email passwdcolumn=password crypt=1 |
pwcheck_method: saslauthd mech_list: plain login allow_plaintext: true auxprop_plugin: mysql sql_hostnames: 127.0.0.1 sql_user: mail_admin sql_passwd: mail_admin_password sql_database: mail sql_select: select password from users where email = '%u' |
[...] authmodulelist="authmysql" [...] |
MYSQL_SERVER localhost MYSQL_USERNAME mail_admin MYSQL_PASSWORD mail_admin_password MYSQL_PORT 0 MYSQL_DATABASE mail MYSQL_USER_TABLE users MYSQL_CRYPT_PWFIELD password #MYSQL_CLEAR_PWFIELD password MYSQL_UID_FIELD 5000 MYSQL_GID_FIELD 5000 MYSQL_LOGIN_FIELD email MYSQL_HOME_FIELD "/home/vmail" MYSQL_MAILDIR_FIELD CONCAT(SUBSTRING_INDEX(email,'@',-1),'/',SUBSTRING_INDEX(email,'@',1),'/') #MYSQL_NAME_FIELD MYSQL_QUOTA_FIELD quota |
[...] CN=server1.example.com [...] |
[...] CN=server1.example.com [...] |
[...] postmaster: root root: [email protected] [...] |
[...] postmaster: root root: administrator [...] |
use strict; # You can modify this file to re-enable SPAM checking through spamassassin # and to re-enable antivirus checking. # # Default antivirus checking mode # Please note, that anti-virus checking is DISABLED by # default. # If You wish to enable it, please uncomment the following lines: @bypass_virus_checks_maps = ( \%bypass_virus_checks, \@bypass_virus_checks_acl, \$bypass_virus_checks_re); # # Default SPAM checking mode # Please note, that anti-spam checking is DISABLED by # default. # If You wish to enable it, please uncomment the following lines: @bypass_spam_checks_maps = ( \%bypass_spam_checks, \@bypass_spam_checks_acl, \$bypass_spam_checks_re); 1; # ensure a defined return |
[...] $QUARANTINEDIR = "$MYHOME/virusmails"; $quarantine_subdir_levels = 1; # enable quarantine dir hashing $log_recip_templ = undef; # disable by-recipient level-0 log entries $DO_SYSLOG = 1; # log via syslogd (preferred) $syslog_ident = 'amavis'; # syslog ident tag, prepended to all messages $syslog_facility = 'mail'; $syslog_priority = 'debug'; # switch to info to drop debug output, etc $enable_db = 1; # enable use of BerkeleyDB/libdb (SNMP and nanny) $enable_global_cache = 1; # enable use of libdb-based cache if $enable_db=1 $inet_socket_port = 10024; # default listening socket $sa_spam_subject_tag = '***SPAM*** '; $sa_tag_level_deflt = 2.0; # add spam info headers if at, or above that level $sa_tag2_level_deflt = 6.31; # add 'spam detected' headers at that level $sa_kill_level_deflt = 6.31; # triggers spam evasive actions $sa_dsn_cutoff_level = 10; # spam level beyond which a DSN is not sent [...] $final_virus_destiny = D_DISCARD; # (data not lost, see virus quarantine) $final_banned_destiny = D_BOUNCE; # D_REJECT when front-end MTA $final_spam_destiny = D_BOUNCE; $final_bad_header_destiny = D_PASS; # False-positive prone (for spam) [...] |
use strict; # # Place your configuration directives here. They will override those in # earlier files. # # See /usr/share/doc/amavisd-new/ for documentation and examples of # the directives you can use in this file # $pax='pax'; #------------ Do not modify anything below this line ------------- 1; # ensure a defined return |
[...] amavis unix - - - - 2 smtp -o smtp_data_done_timeout=1200 -o smtp_send_xforward_command=yes 127.0.0.1:10025 inet n - - - - smtpd -o content_filter= -o local_recipient_maps= -o relay_recipient_maps= -o smtpd_restriction_classes= -o smtpd_client_restrictions= -o smtpd_helo_restrictions= -o smtpd_sender_restrictions= -o smtpd_recipient_restrictions=permit_mynetworks,reject -o mynetworks=127.0.0.0/8 -o strict_rfc821_envelopes=yes -o receive_override_options=no_unknown_recipient_checks,no_header_body_checks -o smtpd_bind_address=127.0.0.1 |
[...] #dcc use_dcc 1 dcc_path /usr/local/bin/dccproc #pyzor use_pyzor 1 pyzor_path /usr/bin/pyzor #razor use_razor2 1 razor_config /etc/razor/razor-agent.conf #bayes use_bayes 1 use_bayes_rules 1 bayes_auto_learn 1 |
[...] # DCC - perform DCC message checks. # # DCC is disabled here because it is not open source. See the DCC # license for more details. # loadplugin Mail::SpamAssassin::Plugin::DCC [...] |
23 4 */2 * * /usr/bin/sa-update --no-gpg &> /dev/null |
#!/usr/bin/perl -w # Author <[email protected]> # # This script assumes that virtual_mailbox_base in defined # in postfix's main.cf file. This directory is assumed to contain # directories which themselves contain your virtual user's maildirs. # For example: # # -----------/ # | # | # home/vmail/domains/ # | | # | | # example.com/ foo.com/ # | # | # ----------------- # | | | # | | | # user1/ user2/ user3/ # | # | # maildirsize # use strict; my $POSTFIX_CF = "/etc/postfix/main.cf"; my $MAILPROG = "/usr/sbin/sendmail -t"; my $WARNPERCENT = 80; my @POSTMASTERS = ('[email protected]'); my $CONAME = 'My Company'; my $COADDR = '[email protected]'; my $SUADDR = '[email protected]'; my $MAIL_REPORT = 1; my $MAIL_WARNING = 1; #get virtual mailbox base from postfix config open(PCF, "< $POSTFIX_CF") or die $!; my $mboxBase; while (<PCF>) { next unless /virtual_mailbox_base\s*=\s*(.*)\s*/; $mboxBase = $1; } close(PCF); #assume one level of subdirectories for domain names my @domains; opendir(DIR, $mboxBase) or die $!; while (defined(my $name = readdir(DIR))) { next if $name =~ /^\.\.?$/; #skip '.' and '..' next unless (-d "$mboxBase/$name"); push(@domains, $name); } closedir(DIR); #iterate through domains for username/maildirsize files my @users; chdir($mboxBase); foreach my $domain (@domains) { opendir(DIR, $domain) or die $!; while (defined(my $name = readdir(DIR))) { next if $name =~ /^\.\.?$/; #skip '.' and '..' next unless (-d "$domain/$name"); push(@users, {"$name\@$domain" => "$mboxBase/$domain/$name"}); } } closedir(DIR); #get user quotas and percent used my (%lusers, $report); foreach my $href (@users) { foreach my $user (keys %$href) { my $quotafile = "$href->{$user}/maildirsize"; next unless (-f $quotafile); open(QF, "< $quotafile") or die $!; my ($firstln, $quota, $used); while (<QF>) { my $line = $_; if (! $firstln) { $firstln = 1; die "Error: corrupt quotafile $quotafile" unless ($line =~ /^(\d+)S/); $quota = $1; last if (! $quota); next; } die "Error: corrupt quotafile $quotafile" unless ($line =~ /\s*(-?\d+)/); $used += $1; } close(QF); next if (! $used); my $percent = int($used / $quota * 100); $lusers{$user} = $percent unless not $percent; } } #send a report to the postmasters if ($MAIL_REPORT) { open(MAIL, "| $MAILPROG"); select(MAIL); map {print "To: $_\n"} @POSTMASTERS; print "From: $COADDR\n"; print "Subject: Daily Quota Report.\n"; print "DAILY QUOTA REPORT:\n\n"; print "----------------------------------------------\n"; print "| % USAGE | ACCOUNT NAME |\n"; print "----------------------------------------------\n"; foreach my $luser ( sort { $lusers{$b} <=> $lusers{$a} } keys %lusers ) { printf("| %3d | %32s |\n", $lusers{$luser}, $luser); print "---------------------------------------------\n"; } print "\n--\n"; print "$CONAME\n"; close(MAIL); } #email a warning to people over quota if ($MAIL_WARNING) { foreach my $luser (keys (%lusers)) { next unless $lusers{$luser} >= $WARNPERCENT; # skip those under quota open(MAIL, "| $MAILPROG"); select(MAIL); print "To: $luser\n"; map {print "BCC: $_\n"} @POSTMASTERS; print "From: $SUADDR\n"; print "Subject: WARNING: Your mailbox is $lusers{$luser}% full.\n"; print "Reply-to: $SUADDR\n"; print "Your mailbox: $luser is $lusers{$luser}% full.\n\n"; print "Once your e-mail box has exceeded your monthly storage quota\n"; print "your monthly billing will be automatically adjusted.\n"; print "Please consider deleting e-mail and emptying your trash folder to clear some space.\n\n"; print "Contact <$SUADDR> for further assistance.\n\n"; print "Thank You.\n\n"; print "--\n"; print "$CONAME\n"; close(MAIL); } } |
0 0 * * * /usr/local/sbin/quota_notify &> /dev/null |
fuente | destino | |
[correo electrónico protegido] | [correo electrónico protegido] | Redirige correos electrónicos de [email protected] a [email protected] |
@ejemplo.com | [correo electrónico protegido] | Crea una cuenta Catch-All para [email protected] Todos los correos electrónicos a example.com llegarán a [email protected], excepto aquellos que existen en la tabla de usuarios (es decir, si [email protected] existe en la tabla de usuarios, los correos electrónicos a [email protected] seguirán llegando a [email protected]). |
@ejemplo.com | @otrodominio.tld | Esto redirige todos los correos electrónicos a ejemplo.com al mismo usuario en otrodominio.tld. Por ejemplo, los correos electrónicos a [email protected] se reenviarán a [email protected] |
[correo electrónico protegido] | [correo electrónico protegido], [correo electrónico protegido]principal.tld | Reenviar correos electrónicos para [email protected] a dos o más direcciones de correo electrónico. Todas las direcciones de correo electrónico enumeradas en destino reciben una copia del correo electrónico. |
dominio | transporte | |
ejemplo.com | : | Entrega correos electrónicos para example.com localmente. Esto es como si este registro no existiera en absoluto en esta tabla. |
ejemplo.com | smtp:mail.otrodominio.tld | Envía todos los correos electrónicos de example.com a través de smtp al servidor mail.anotherdomain.com. |
ejemplo.com | smtp:mail.otrodominio.tld:2025 | Envía todos los correos electrónicos de example.com a través de smtp al servidor mail.anotherdomain.com, pero en el puerto 2025, no en el 25, que es el puerto predeterminado para smtp. |
ejemplo.com |
smtp:[1.2.3.4] | Los corchetes evitan que Postfix realice búsquedas del registro MX DNS para la dirección entre corchetes. Tiene sentido para las direcciones IP. |
.ejemplo.com | smtp:mail.otrodominio.tld | El correo de cualquier subdominio de example.com se envía a mail.anotherdomain.tld. |
* | smtp:mail.otrodominio.tld | Todos los correos electrónicos se envían a mail.anotherdomain.tld. |
[correo electrónico protegido] | smtp:mail.otrodominio.tld | Los correos electrónicos para [email protected] se envían a mail.anotherdomain.tld. |
[...] $csp_dsn = 'mysql://mail_admin:[email protected]/mail'; [...] $lookup_password_query = 'SELECT count(*) FROM users WHERE email = "%1" AND password = %4'; [...] $password_update_queries = array('UPDATE users SET password = %4 WHERE email = "%1"'); [...] $password_encryption = 'MYSQLENCRYPT'; [...] $csp_salt_static = 'LEFT(password, 2)'; [...] //$csp_salt_query = 'SELECT salt FROM users WHERE username = "%1"'; [...] $csp_delimiter = '@'; [...] |
<?php /** * SquirrelMail Change SQL Password Plugin * Copyright (C) 2001-2002 Tyler Akins * 2002 Thijs Kinkhorst <[email protected]> * 2002-2005 Paul Lesneiwski <[email protected]> * This program is licensed under GPL. See COPYING for details * * @package plugins * @subpackage Change SQL Password * */ // Global Variables, don't touch these unless you want to break the plugin // global $csp_dsn, $password_update_queries, $lookup_password_query, $force_change_password_check_query, $password_encryption, $csp_salt_query, $csp_salt_static, $csp_secure_port, $csp_non_standard_http_port, $csp_delimiter, $csp_debug, $min_password_length, $max_password_length, $include_digit_in_password, $include_uppercase_letter_in_password, $include_lowercase_letter_in_password, $include_nonalphanumeric_in_password; // csp_dsn // // Theoretically, any SQL database supported by Pear should be supported // here. The DSN (data source name) must contain the information needed // to connect to your database backend. A MySQL example is included below. // For more details about DSN syntax and list of supported database types, // please see: // http://pear.php.net/manual/en/package.database.db.intro-dsn.php // //$csp_dsn = 'mysql://user:[email protected]/email_users'; $csp_dsn = 'mysql://mail_admin:[email protected]/mail'; // lookup_password_query // // This plugin will always verify the user's old password // against their login password, but an extra check can also // be done against the database for more security if you // desire. If you do not need the extra password check, // make sure this setting is empty. // // This is a query that returns a positive value if a user // and password pair are found in the database. // // This query should return one value (one row, one column), the // value being ideally a one or a zero, simply indicating that // the user/password pair does in fact exist in the database. // // %1 in this query will be replaced with the full username // (including domain), such as "[email protected]" // %2 in this query will be replaced with the username (without // any domain portion), such as "jose" // %3 in this query will be replaced with the domain name, // such as "example.com" // %4 in this query will be replaced with the current (old) // password in whatever encryption format is needed per other // plugin configuration settings (Note that the syntax of // the password will be provided depending on your encryption // choices, so you NEVER need to provide quotes around this // value in the query here.) // %5 in this query will be replaced with the current (old) // password in unencrypted plain text. If you do not use any // password encryption, %4 and %5 will be the same values, // except %4 will have double quotes around it and %5 will not. // //$lookup_password_query = ''; // TERRIBLE SECURITY: $lookup_password_query = 'SELECT count(*) FROM users WHERE username = "%1" AND plain_password = "%5"'; //$lookup_password_query = 'SELECT count(*) FROM users WHERE username = "%1" AND crypt_password = %4'; $lookup_password_query = 'SELECT count(*) FROM users WHERE email = "%1" AND password = %4'; // password_update_queries // // An array of SQL queries that will all be executed // whenever a password change attempt is made. // // Any number of queries may be included here. // The queries will be executed in the order given here. // // %1 in all queries will be replaced with the full username // (including domain), such as "[email protected]" // %2 in all queries will be replaced with the username (without // any domain portion), such as "jose" // %3 in all queries will be replaced with the domain name, // such as "example.com" // %4 in all queries will be replaced with the new password // in whatever encryption format is needed per other // plugin configuration settings (Note that the syntax of // the password will be provided depending on your // encryption choices, so you NEVER need to provide quotes // around this value in the queries here.) // %5 in all queries will be replaced with the new password // in unencrypted plain text - BEWARE! If you do not use // any password encryption, %4 and %5 will be the same // values, except %4 will have double quotes around it // and %5 will not. // // $password_update_queries = array( // 'UPDATE users SET crypt_password = %4 WHERE username = "%1"', // 'UPDATE user_flags SET force_change_pwd = 0 WHERE username = "%1"', // 'UPDATE users SET crypt_password = %4, force_change_pwd = 0 WHERE username = "%1"', // ); $password_update_queries = array('UPDATE users SET password = %4 WHERE email = "%1"'); // force_change_password_check_query // // A query that checks for a flag that indicates if a user // should be forced to change their password. This query // should return one value (one row, one column) which is // zero if the user does NOT need to change their password, // or one if the user should be forced to change it now. // // This setting should be an empty string if you do not wish // to enable this functionality. // // %1 in this query will be replaced with the full username // (including domain), such as "[email protected]" // %2 in this query will be replaced with the username (without // any domain portion), such as "jose" // %3 in this query will be replaced with the domain name, // such as "example.com" // //$force_change_password_check_query = 'SELECT IF(force_change_pwd = "yes", 1, 0) FROM users WHERE username = "%1"'; //$force_change_password_check_query = 'SELECT force_change_pwd FROM users WHERE username = "%1"'; $force_change_password_check_query = ''; // password_encryption // // What encryption method do you use to store passwords // in your database? Please use one of the following, // exactly as you see it: // // NONE Passwords are stored as plain text only // MYSQLPWD Passwords are stored using the MySQL password() function // MYSQLENCRYPT Passwords are stored using the MySQL encrypt() function // PHPCRYPT Passwords are stored using the PHP crypt() function // MD5CRYPT Passwords are stored using encrypted MD5 algorithm // MD5 Passwords are stored as MD5 hash // //$password_encryption = 'MYSQLPWD'; $password_encryption = 'MYSQLENCRYPT'; // csp_salt_query // csp_salt_static // // Encryption types that need a salt need to know where to get // that salt. If you have a constant, known salt value, you // should define it in $csp_salt_static. Otherwise, leave that // value empty and define a value for the $csp_salt_query. // // Leave both values empty if you do not need (or use) salts // to encrypt your passwords. // // The query should return one value (one row, one column) which // is the salt value for the current user's password. This // query is ignored if $csp_salt_static is anything but empty. // // %1 in this query will be replaced with the full username // (including domain), such as "[email protected]" // %2 in this query will be replaced with the username (without // any domain portion), such as "jose" // %3 in this query will be replaced with the domain name, // such as "example.com" // //$csp_salt_static = 'LEFT(crypt_password, 2)'; //$csp_salt_static = '"a4"'; // use this format with MYSQLENCRYPT //$csp_salt_static = '$2$blowsomefish$'; // use this format with PHPCRYPT //$csp_salt_static = ''; $csp_salt_static = 'LEFT(password, 2)'; //$csp_salt_query = 'SELECT SUBSTRING_INDEX(crypt_password, '$', 1) FROM users WHERE username = "%1"'; //$csp_salt_query = 'SELECT SUBSTRING(crypt_password, (LENGTH(SUBSTRING_INDEX(crypt_password, '$', 2)) + 2)) FROM users WHERE username = "%1"'; //$csp_salt_query = 'SELECT salt FROM users WHERE username = "%1"'; //$csp_salt_query = ''; // csp_secure_port // // You may ensure that SSL encryption is used during password // change by setting this to the port that your HTTPS is served // on (443 is typical). Set to zero if you do not wish to force // an HTTPS connection when users are changing their passwords. // // You may override this value for certain domains, users, or // service levels through the Virtual Host Login (vlogin) plugin // by setting a value(s) for $vlogin_csp_secure_port in the vlogin // configuration. // $csp_secure_port = 0; //$csp_secure_port = 443; // csp_non_standard_http_port // // If you serve standard HTTP web requests on a non-standard // port (anything other than port 80), you should specify that // port number here. Set to zero otherwise. // // You may override this value for certain domains, users, or // service levels through the Virtual Host Login (vlogin) plugin // by setting a value(s) for $vlogin_csp_non_standard_http_port // in the vlogin configuration. // //$csp_non_standard_http_port = 8080; $csp_non_standard_http_port = 0; // min_password_length // max_password_length // include_digit_in_password // include_uppercase_letter_in_password // include_lowercase_letter_in_password // include_nonalphanumeric_in_password // // You can set the minimum and maximum password lengths that // you accept or leave those settings as zero to indicate that // no limit should be applied. // // Turn on any of the other settings here to check that the // new password contains at least one digit, upper case letter, // lower case letter and/or one non-alphanumeric character. // $min_password_length = 6; $max_password_length = 0; $include_digit_in_password = 0; $include_uppercase_letter_in_password = 0; $include_lowercase_letter_in_password = 0; $include_nonalphanumeric_in_password = 0; // csp_delimiter // // if your system has usernames with something other than // an "@" sign separating the user and domain portion, // specify that character here // //$csp_delimiter = '|'; $csp_delimiter = '@'; // debug mode // $csp_debug = 0; ?> |