commit 5675cc832a13c52988cd371ae480fe8aa46a5275
Author: Хирецкий Михаил <mh@calculate.ru>
Date:   Mon Sep 17 14:11:29 2018 +0300

    Исправлена настройка почтового сервиса и генерации сертификатов
    
    * исправлена генереация сертификатов для mail сервиса и jabber
    * добавлена генерация сертификтаов при выполнении cl-update-server
    * исправлена конфигурационные файлы для postfix
    * добавлена поддержка dh параметра для dovecot

diff --git a/profile/mail/etc/dovecot/conf.d/10-ssl.conf b/profile/mail/etc/dovecot/conf.d/10-ssl.conf
new file mode 100644
index 0000000..4b08b5e
--- /dev/null
+++ b/profile/mail/etc/dovecot/conf.d/10-ssl.conf
@@ -0,0 +1,8 @@
+# Calculate format=dovecot chmod=0644 chown=root:root
+
+#?pkg(net-mail/dovecot)>=2.3#
+ssl_dh = </etc/ssl/dovecot/dh.pem
+#pkg#
+#?pkg(net-mail/dovecot)<2.3#
+!ssl_dh = del
+#pkg#
diff --git a/profile/mail/etc/postfix/main.cf b/profile/mail/etc/postfix/main.cf
index de16ede..01058ee 100644
--- a/profile/mail/etc/postfix/main.cf
+++ b/profile/mail/etc/postfix/main.cf
@@ -16,10 +16,10 @@ command_directory = /usr/sbin
 # daemon programs (i.e. programs listed in the master.cf file). This
 # directory must be owned by root.
 #
-#pkg(mail-mta/postfix)<2.9.3#
+#?pkg(mail-mta/postfix)<2.9.3#
 daemon_directory = /usr/lib/postfix
 #pkg#
-#pkg(mail-mta/postfix)>=2.9.3#
+#?pkg(mail-mta/postfix)>=2.9.3#
 daemon_directory = /usr/libexec/postfix
 #pkg#
 
@@ -205,10 +205,10 @@ smtp_tls_session_cache_database = btree:${queue_directory}/smtp_scache
 
 #включаем авторизацию через dovecot
 smtpd_sasl_auth_enable = yes
-#pkg(mail-mta/postfix)<2.10.1#
+#?pkg(mail-mta/postfix)<2.10.1#
 smtpd_sasl2_auth_enable = yes
 #pkg#
-#pkg(mail-mta/postfix)>=2.10.1#
+#?pkg(mail-mta/postfix)>=2.10.1#
 !smtpd_sasl2_auth_enable = del
 #pkg#
 smtpd_sasl_type = dovecot
@@ -340,3 +340,4 @@ non_smtpd_milters = inet:localhost:2525
 # В случае почтового релея удаляем mailbox_command
 #?sr_mail_relay_set==on#!mailbox_command = #sr_mail_relay_set#
 #?sr_mail_relay_set==off#mailbox_command = /usr/bin/procmail -m /etc/procmailrc#sr_mail_relay_set#
+smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, defer_unauth_destination
diff --git a/pym/cl_ldap.py b/pym/cl_ldap.py
index 49273d7..5480365 100644
--- a/pym/cl_ldap.py
+++ b/pym/cl_ldap.py
@@ -1835,6 +1835,38 @@ This command is not allowed."))
         else:
             return self.dialogYesNo(message)
 
+    def createJabberCertificate(self):
+        # создаем сертификат если есть используем прежний
+        if not os.path.exists("/etc/jabber/ssl.pem"):
+            if os.path.exists("/etc/jabber/self-cert.sh"):
+                self.execProg("/bin/bash /etc/jabber/self-cert.sh")
+            else:
+                # Создаем сертификат для Ejabberd
+                if not self.createCertificate(sslOrganization=\
+                                     "Automatically-generated ejabberd SSL key",
+                                              userName="jabber",
+                                              groupName="jabber",
+                                              certFile="/etc/jabber/ssl.pem",
+                                              genDH=True):
+                    return False
+        return True
+
+    def createMailCertificate(self):
+        if not self.createCertificate(sslOrganization="Dovecot IMAP Server",
+                                userName="dovecot", groupName="mail",
+                                certFile="/etc/ssl/dovecot/server.pem",
+                                dhFile="/etc/ssl/dovecot/dh.pem",
+                                genDH=True,
+                                keyFile="/etc/ssl/dovecot/server.key"):
+            return False
+        # Создаем сертификат для Postfix
+        if not self.createCertificate(sslOrganization="Postfix IMAP Server",
+                                userName="postfix", groupName="postfix",
+                                certFile="/etc/ssl/postfix/server.pem",
+                                keyFile="/etc/ssl/postfix/server.key"):
+            return False
+        return True
+
     def createCertificate(self, sslCountry="US",
                                 sslState="California",
                                 sslLocality="Santa Barbara",
@@ -1850,21 +1882,49 @@ This command is not allowed."))
                                 certFileMode=0400,
                                 keyFile="/tmp/server.key",
                                 keyFileMode=0400,
+                                dhFile=None,
+                                dhFileMode=0400,
                                 genDH=False):
         """Создает сертификат"""
-        if genDH:
-            keyFile = certFile
-            certAndKeyFiles = [certFile]
-            foundCertFiles = filter(lambda x: os.path.exists(x),certAndKeyFiles)
-            if len(foundCertFiles)==1:
-                return True
-        else:
-            certAndKeyFiles = [certFile, keyFile]
+        sslFile = "/usr/bin/openssl"
+        strData = time.strftime("%Y%m%d%H%M%S",time.localtime(time.time()))
+        if not os.path.exists(sslFile):
+            self.printERROR(_("Can not found %s")%sslFile)
+            return False
+
+        if genDH and dhFile:
+            certAndKeyFiles = [dhFile, certFile, keyFile]
             foundCertFiles = filter(lambda x: os.path.exists(x), certAndKeyFiles)
-            if len(foundCertFiles)==2:
+            if not os.path.exists(dhFile):
+                rndFile = "/tmp/%s.rnd" %strData
+                self.execProg("dd if=/dev/urandom of=%s count=1"%rndFile)
+                if not os.path.exists(rndFile):
+                    self.printERROR(_("Can not create %s")%rndFile)
+                    return False
+                textLine = self.execProg("%s gendh -rand %s 512 >> %s"\
+                                         %(sslFile, rndFile, dhFile))
+                if textLine == False:
+                    self.printERROR(_("Can not create DH certificate %s")%certFile)
+                    return False
+                if os.path.exists(rndFile):
+                    os.remove(rndFile)
+            foundCertFiles = filter(lambda x: os.path.exists(x), certAndKeyFiles)
+            if len(foundCertFiles)==3:
                 return True
-        # Удаляем файл сертификата
-        map(lambda x: os.remove(x), foundCertFiles)
+        else:
+            if genDH:
+                keyFile = certFile
+                certAndKeyFiles = [certFile]
+                foundCertFiles = filter(lambda x: os.path.exists(x),certAndKeyFiles)
+                if len(foundCertFiles)==1:
+                    return True
+            else:
+                certAndKeyFiles = [certFile, keyFile]
+                foundCertFiles = filter(lambda x: os.path.exists(x), certAndKeyFiles)
+                if len(foundCertFiles)==2:
+                    return True
+            # Удаляем файл сертификата
+            map(lambda x: os.remove(x), foundCertFiles)
         uidAndGid  = self.getUserUidAndGid(userName, groupName)
         if not uidAndGid:
             return False
@@ -1888,7 +1948,6 @@ nsCertType = %s
 """%(sslBits, sslCountry, sslState, sslLocality, sslOrganization, sslUnit,
      sslCommonName, sslEmail, nsCertType)
         # генерируем название файла конфигурации
-        strData = time.strftime("%Y%m%d%H%M%S",time.localtime(time.time()))
         cnfFile = "/tmp/%s.cnf" %strData
         if genDH:
             rndFile = "/tmp/%s.rnd" %strData
@@ -1896,10 +1955,6 @@ nsCertType = %s
             if not os.path.exists(rndFile):
                 self.printERROR(_("Can not create %s")%rndFile)
                 return False
-        sslFile = "/usr/bin/openssl"
-        if not os.path.exists(sslFile):
-            self.printERROR(_("Can not found %s")%sslFile)
-            return False
         # Cоздание директорий
         for fileName in certAndKeyFiles:
             dirName = os.path.split(fileName)[0]
@@ -4835,11 +4890,7 @@ if you want to continue to run the program again"))
         self.clVars.Set("sr_mail_crypt", mailCrypt, True)
         if not self.applyProfilesFromService('mail'):
             return False
-        # Создаем сертификат для Dovecot
-        if not self.createCertificate(sslOrganization="Dovecot IMAP Server",
-                                userName="dovecot", groupName="mail",
-                                certFile="/etc/ssl/dovecot/server.pem",
-                                keyFile="/etc/ssl/dovecot/server.key"):
+        if not self.createMailCertificate():
             return False
         # Проверим запущен ли ldap
         if not self.getRunService("ldap"):
@@ -5708,18 +5759,8 @@ in Unix service") %str(jabberId))
              "PASS":self.clVars.Get("ld_jabber_pw")})
         self.printOK(_("Added ldif file") + " ...")
         # создаем сертификат если есть используем прежний
-        if not os.path.exists("/etc/jabber/ssl.pem"):
-            if os.path.exists("/etc/jabber/self-cert.sh"):
-                self.execProg("/bin/bash /etc/jabber/self-cert.sh")
-            else:
-                # Создаем сертификат для Ejabberd
-                if not self.createCertificate(sslOrganization=\
-                                     "Automatically-generated ejabberd SSL key",
-                                              userName="jabber",
-                                              groupName="jabber",
-                                              certFile="/etc/jabber/ssl.pem",
-                                              genDH=True):
-                    return False
+        if not self.createJabberCertificate():
+            return False
         if not os.path.exists("/etc/jabber/ssl.pem"):
             self.printERROR(_("Can not create Jabber certificate"))
             return False
@@ -7497,6 +7538,9 @@ outdated. If the backup is obsolete, use cl-backup-server."))
                 self.clVars.Set("sr_proxy_host",fullHostName,True)
         # Настройка почты
         if serviceUpdate in ["all","mail"]:
+            # Создаем сертификат для Dovecot
+            if not self.createMailCertificate():
+                return False
             history,history_domain,history_path = \
                 self.getMailHistoryData(options)
             if options.has_key("t"):
@@ -7525,6 +7569,8 @@ outdated. If the backup is obsolete, use cl-backup-server."))
         previousJabberHost = self.clVars.Get("sr_jabber_host")
         if serviceUpdate in ["all","jabber"]:
             # Устанавливаем основной хост jabber cервиса
+            if not self.createJabberCertificate():
+                return False
             if options.has_key("host"):
                 newHostName = options['host']
                 if not "." in newHostName:
