Archives pour la catégorie ‘Thunderbird’

Dovecot : restriction de l’authentification utilisateur

Je vous présente ici la solution que j’ai retenu pour restreindre les possibilités d’authentification de Dovecot selon le protocole utilisé (POP/IMAP/SMTP/Sieve). La gestion des comptes de messagerie étant effectué en SQL avec PostfixAdmin, le schéma a été repris tel quel ; seule une table a été ajoutée. L’authentification SMTP est déportée de Postfix vers Dovecot (configuration LMTP).

Configuration SQL

La table dédiée à l’authentification est la suivante :

CREATE TABLE IF NOT EXISTS `auth` (
  `username` varchar(255) NOT NULL,
  `allow_smtp` tinyint(1) NOT NULL DEFAULT '1',
  `smtp_nets` varchar(255) NOT NULL DEFAULT '::1,127.0.0.1,0::0/0,0.0.0.0/0',
  `allow_imap` tinyint(1) NOT NULL DEFAULT '1',
  `imap_nets` varchar(255) NOT NULL DEFAULT '::1,127.0.0.1',
  `allow_pop3` tinyint(1) NOT NULL DEFAULT '1',
  `pop3_nets` varchar(255) NOT NULL DEFAULT '::1,127.0.0.1,0::0/0,0.0.0.0/0',
  `allow_sieve` tinyint(1) NOT NULL DEFAULT '1',
  `sieve_nets` varchar(255) NOT NULL DEFAULT '::1,127.0.0.1',
  PRIMARY KEY (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Elle contiendra donc l’ensemble des comptes utilisateurs (username) avec les possibilités de chacun. Les valeurs par défaut autorisent ici :

  • la connexion SMTP quelque soit l’IP source (IPv4 et IPv6)
  • la connexion IMAP uniquement par IP locale (par webmail)
  • la connexion POP3 quelque soit l’IP source
  • la gestion des filtres Sieve uniquement en local (par webmail)

Configuration de Dovecot

Les requêtes SQL sont à modifier de cette façon :

user_query = \
   SELECT \
      CONCAT('/var/spool/vmail/', maildir) AS home, \
      CONCAT('maildir:/var/spool/vmail/', maildir) AS mail, \
      999 AS uid, \
      999 AS gid, \
      'dict:User quota::proxy::quota' AS quota, \
      CONCAT('*:storage=',FLOOR(quota/1000)) AS quota_rule, \
      'Trash:storage=+100M' AS quota_rule2 \
   FROM \
      mailbox \
   WHERE \
      username='%u' AND domain='%d' AND active='1'

password_query = \
   SELECT \
      mailbox.username AS user, \
      mailbox.domain AS domain, \
      password, \
      CONCAT('/var/spool/vmail/', maildir) AS userdb_home, \
      CONCAT('maildir:/var/spool/vmail/', maildir) AS userdb_mail, \
      999 AS userdb_uid, \
      999 AS userdb_gid, \
      'dict:User quota::proxy::quota' AS userdb_quota, \
      CONCAT('*:storage=',FLOOR(quota/1000)) AS userdb_quota_rule, \
      'Trash:storage=+100M' AS userdb_quota_rule2, \
      CASE '%s' \
         WHEN 'smtp' THEN smtp_nets \
         WHEN 'imap' THEN imap_nets \
         WHEN 'pop3' THEN pop3_nets \
         WHEN 'sieve' THEN sieve_nets \
      END AS allow_nets \
   FROM \
      mailbox, auth \
   WHERE \
      mailbox.username=auth.username AND \
      mailbox.username='%u' AND domain='%d' AND active='1' AND \
      ( \
         ('%s'='smtp' AND allow_smtp='1') \
         OR \
         ('%s'='imap' AND allow_imap='1') \
         OR \
         ('%s'='pop3' AND allow_pop3='1') \
         OR \
         ('%s'='sieve' AND allow_sieve='1') \
         OR \
         '%s'='doveadm' \
      )

iterate_query = \
   SELECT \
      username AS user \
   FROM \
      mailbox \
   WHERE \
      active='1'

Scripts complémentaires pour une gestion avec Postfixadmin

Du côté de PostfixAdmin, l’ajout et la suppresion de comptes déclenchent les scripts de modification des enregistrements dans la table auth :

root@mail:~# more mailbox-postcreation.d/10-auth
#!/usr/bin/perl

my $sql_host = 'localhost';                         # SQL server hostname
my $sql_port = '3306';                              # SQL server port
my $sql_database = 'postfix';                       # SQL database name
my $sql_user = 'postfixadmin';                      # SQL user
my $sql_password = 'blablablaaa';                   # SQL password

use strict;
use warnings;
use DBI;
use DBD::mysql;

my ($dsn, $dbh, $qh, $mailbox);

$mailbox = $ARGV[0];
if (!defined($mailbox) || ($mailbox eq '')) {
   exit 1
}

$dsn = "dbi:mysql:$sql_database:$sql_host:$sql_port";
$dbh = DBI->connect($dsn, $sql_user, $sql_password)
	or die "failed to connect to database: $DBI::errstr\n";
$qh = $dbh->prepare("INSERT INTO auth (username) VALUES ('$mailbox')");
$qh->execute();
root@mail:~# more /root/scripts/postfixadmin/mailbox-postdeletion.d/10-auth
#!/usr/bin/perl

my $sql_host = 'localhost';                         # SQL server hostname
my $sql_port = '3306';                              # SQL server port
my $sql_database = 'postfix';                       # SQL database name
my $sql_user = 'postfixadmin';                      # SQL user
my $sql_password = 'blablablaaa';                   # SQL password

use strict;
use warnings;
use DBI;
use DBD::mysql;

my ($dsn, $dbh, $qh, $mailbox);

$mailbox = $ARGV[0];
if (!defined($mailbox) || ($mailbox eq '')) {
   exit 1
}

$dsn = "dbi:mysql:$sql_database:$sql_host:$sql_port";
$dbh = DBI->connect($dsn, $sql_user, $sql_password)
	or die "failed to connect to database: $DBI::errstr\n";
$qh = $dbh->prepare("DELETE FROM auth WHERE username='$mailbox'");
$qh->execute();

Script pour autoconfiguration avec Thunderbird

Je vous renvoie sur mon article présentant l’autoconfiguration d’un compte sous Thunderbird. L’intérêt du script PHP est de récupérer les paramètres adaptés/autorisés pour l’utilisateur concerné.

<?php
/*
 * autoconf.php
 *
 * Boris HUISGEN <bhuisgen@hbis.fr>
 */

   define("SYSLOG_IDENT", "autoconfig");
   define("SYSLOG_OPTIONS", LOG_PID|LOG_NDELAY);
   define("SYSLOG_LOCAL", LOG_USER);
   define("DB_DSN", "mysql:host=localhost;dbname=postfix");
   define("DB_USER", "autoconfig");
   define("DB_PASSWORD", "blablablaaa");
   define("REGEX_ALLOWNETS", "/^(.*,)?(0::0\/0|0\.0\.0\.0\/0)(,.*)$/");

   // script

   openlog(SYSLOG_IDENT, SYSLOG_OPTIONS, SYSLOG_LOCAL);

   if (getenv("HTTP_CLIENT_IP"))
      $ip = getenv("HTTP_CLIENT_IP");
   else if(getenv("HTTP_X_FORWARDED_FOR"))
      $ip = getenv("HTTP_X_FORWARDED_FOR");
   else if(getenv("REMOTE_ADDR"))
      $ip = getenv("REMOTE_ADDR");
   else $ip = "unknown IP";

   if (!isset($_GET["emailaddress"]))
   {
      syslog(LOG_ERR, "[client=$ip] failed to get email address, aborting execution");
      exit(1);
   }

   $username = $_GET["emailaddress"];
   {
      $c = new PDO(DB_DSN, DB_USER, DB_PASSWORD);
      $c->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

      $s = $c->prepare("SELECT allow_smtp, smtp_nets, allow_pop3, pop3_nets, " .
                          "allow_imap, imap_nets FROM auth WHERE username = ?");
      $s->bindColumn(1, $allow_smtp, PDO::PARAM_INT);
      $s->bindColumn(2, $smtp_nets, PDO::PARAM_STR, 255);
      $s->bindColumn(3, $allow_pop3, PDO::PARAM_INT);
      $s->bindColumn(4, $pop3_nets, PDO::PARAM_STR, 255);
      $s->bindColumn(5, $allow_imap, PDO::PARAM_INT);
      $s->bindColumn(6, $imap_nets, PDO::PARAM_STR, 255);
      $s->bindParam(1, $username);
      $s->execute();
      if ($s->rowCount() != 1)
      {
         syslog(LOG_ERR, "[client=$ip] $username not found");
         exit(3);
      }

      $s->fetch(PDO::FETCH_BOUND);
   }
   catch (PDOException $e)
   {
      syslog(LOG_ERR, "PDO exception, aborting execution");
      exit(2);
   }

   syslog(LOG_NOTICE, "[client=$ip] $username configured");

   header("Content-type: text/xml; charset=utf-8");
?>
<?xml version="1.0" encoding="UTF-8"?>
<clientConfig version="1.1">
  <emailProvider id="domaine.fr">
    <domain>domaine.fr</domain>
    <displayName>Test</displayName>
    <displayShortName>Test</displayShortName>
<?php
   if (($allow_imap == 1) &&
       (preg_match(REGEX_ALLOWNETS, $imap_nets) == 1))
   {
?>
    <incomingServer type="imap">
      <hostname>mail.domaine.fr</hostname>
      <port>143</port>
      <socketType>STARTTLS</socketType>
      <username>%EMAILADDRESS%</username>
      <authentication>password-cleartext</authentication>
    </incomingServer>
<?php
   }

   if (($allow_pop3 == 1) &&
       (preg_match(REGEX_ALLOWNETS, $pop3_nets) == 1))
   {
?>
    <incomingServer type="pop3">
      <hostname>mail.domaine.fr</hostname>
      <port>995</port>
      <socketType>SSL</socketType>
      <authentication>password-cleartext</authentication>
      <username>%EMAILADDRESS%</username>
    </incomingServer>
<?php
   }

   if (($allow_smtp == 1) &&
       (preg_match(REGEX_ALLOWNETS, $smtp_nets) == 1))
   {
?>
    <outgoingServer type="smtp">
      <hostname>noreply.domaine.fr</hostname>
      <port>587</port>
      <socketType>STARTTLS</socketType>
      <username>%EMAILADDRESS%</username>
    </outgoingServer>
<?php
   }
?>
  </emailProvider>
</clientConfig>

Thunderbird : configuration automatique des comptes de messagerie

Tout comme Outlook, le client de messagerie Thunderbird prend en charge la configuration automatique des comptes mail afin de faciliter les utilisateurs (et les administrateurs). Seuls sont donc à fournir l’adresse et le mot de passe de messagerie ; Thunderbird récupère ensuite un fichier XML contenant les paramètres de configuration serveur à l’URL suivante  :

http://autoconfig.<domaine de l’adresse électronique>/mail/config-v1.1.xml

Voici la configuration à mettre en place pour supporter l’autoconfiguration de Thunderbird.

Création du fichier XML

Le fichier XML est modulable selon les protocoles et les options de connexions :

# cat /var/www/autoconfig.xml
<?xml version="1.0" encoding="UTF-8"?>
<clientConfig version="1.1">
  <emailProvider id="hbis.fr">
    <domain>hbis.fr</domain>
    <displayName>mail server</displayName>
    <displayShortName>mail server</displayShortName>
    <incomingServer type="imap">
      <hostname>mail.hbis.fr</hostname>
      <port>143</port>
      <socketType>STARTTLS</socketType>
      <username>%EMAILADDRESS%</username>
      <authentication>password-cleartext</authentication>
    </incomingServer>
    <incomingServer type="pop3">
      <hostname>mail.hbis.fr</hostname>
      <port>995</port>
      <socketType>SSL</socketType>
      <authentication>password-cleartext</authentication>
      <username>%EMAILADDRESS%</username>
    </incomingServer>
    <outgoingServer type="smtp">
      <hostname>mail.hbis.fr</hostname>
      <port>587</port>
      <socketType>STARTTLS</socketType>
      <authentication>password-cleartext</authentication>
      <username>%EMAILADDRESS%</username>
    </outgoingServer>
  </emailProvider>
</clientConfig>

Configuration DNS

Pour chaque domaine de messagerie, un alias autoconfig de type A ou CNAME est à créer en le pointant vers l’adresse du serveur web où le fichier XML est stocké :

autoconfig   IN CNAME mail.hbis.fr

Configuration web

Au niveau du serveur web, l’idéal est de configurer le virtual host par défaut, surtout dans le cas d’une gestion de messagerie multidomaines :

# cat /etc/nginx/sites-enabled/default
server {
   listen		*:80 default_server;
   listen		[::]:80 ipv6only=on default_server;
   server_name     localhost;
   root            /var/www/;
   index           index.html index.php;

   rewrite ^/mail/config-v1\.1\.xml$ /autoconfig.xml;
}

Ajout du compte mail

Lancez Thunderbird et son assistant de création de compte mail. Renseignez votre nom, email, mot de passe et cliquez sur suivant. Thunderbird se charge du reste !

Thunderbird : suppression des fichiers index

bhuisgen$ cd ~/Library/Thunderbird/Profiles/
bhuisgen$ find . -name '*.msf' -print0 | xargs -0 rm
Haut de page